- PVSM.RU - https://www.pvsm.ru -
Анализируя замечания предыдущего поста (Qt Designer & Runtime Qt библиотеки на службе OpenCV... [1]), пришлось более детально проработать устройство видеозахвата библиотеки OpenCV и методы разделения библиотек runtime и виджетов.
Работа с Qt Designer удобна (я — лентяй), поэтому и возник компонент проектирования интерфейса для CvCapture. После начала работы подтянулось и «научное » тому объяснение — удобно применить нечто похожее, скажем, при проектировании интерфейса свойств или параметров приложения, использующего устройство видеозахвата.
Пока идёт скачивание архива проекта [2], читайте далее.
Спасибо всем, кто оставил свои замечания по предыдущему посту.
Итак, библиотека OpenCV установлена, примеры кода просмотрены. Самое время «прикрутить» устройство видеозахвата к Qt. Да не просто так, а чтобы и изображения получать, меняя устройства динамически. Да, чтобы помнило все пути к изображению, видео. Да, чтобы и номера камер переключало. Да, чтобы и… пост покороче получился.
Чего проще! Наследуем новый класс библиотеки от QObject, прячем ненужные разработчику поля и методы в приватный класс как элемент коллекции QScopedPointer, монтируем сигналы оповещения и слоты-обработчики.
Получаем файл заголовка cqtopencvcaptureobject.h
#ifndef CQTOPENCVCAPTUREOBJECT_H
#define CQTOPENCVCAPTUREOBJECT_H
#include "../../../include/qtopencv_global.h"
#include <opencv2/opencv.hpp>
#include <QObject>
#include <QScopedPointer>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
/*----------------------------------------------------------------------------*/
/**
internal
class CQtOpenCVCaptureObjectPrivate
brief Класс скрытого для стороннего разработчика объявлений свойст и реализаций
механизмов работы с устройством видеозахвата типа CvCapture библиотеки OpenCV.
*/
class CQtOpenCVCaptureObjectPrivate;
/*----------------------------------------------------------------------------*/
/**
class CQtOpenCVCaptureObject
brief Класс Работы с устройством видеозахвата типа CvCapture библиотеки OpenCV.
*/
class
#if defined(QTOPENCV_LIB_EXPORT)
QTOPENCV_DECLARE_EXPORT
#else
Q_DECL_EXPORT
#endif
CQtOpenCVCaptureObject : public QObject
{
Q_OBJECT
Q_CLASSINFO("brief", "OpenCV Capture class.")
Q_CLASSINFO("author", "Vladimir N. Litvinenko")
Q_CLASSINFO("URL", "http://www.codepaint.ru")
Q_CLASSINFO("email", "litvinenko.vladimir@gmail.com")
Q_CLASSINFO("created", "21-JUN-2012")
Q_CLASSINFO("edited", "06-JUL-2012")
public:
explicit
CQtOpenCVCaptureObject ( QObject *parent = 0 );
virtual
~CQtOpenCVCaptureObject ();
CvCapture* getCapture () const;
QString getPath () const;
int getNumber () const;
int getTimeoutInterval () const;
IplImage* getImage () const;
int getFrameCount () const;
bool isInternal () const;
bool isExternal () const;
bool isActive () const;
bool isRecap () const;
signals:
/**
fn [SIGNAL] void CQtOpenCVCaptureObject::signal_Errno ( int errno, const QString& errmsg );
brief Сигнал оповещения о возникновении ошибочной ситуации.
param errno - номер ошибки
param errmsg - строка сообщения
*/
void signal_Errno ( int, const QString& );
/**
fn [SIGNAL] void CQtOpenCVCaptureObject::signal_CaptureChanged ()
brief Сигнал оповещения об изменении устройства видеозахвата
*/
void signal_CaptureChanged ();
/**
fn [SIGNAL] void CQtOpenCVCaptureObject::signal_CaptureChanged ( const CvCapture* value )
brief Сигнал оповещения об изменении устройства видеозахвата
param value - указател на новое устройство видеозахвата типа CvCapture
библиотеки OpenCV
*/
void signal_CaptureChanged ( const CvCapture* );
/**
fn [SIGNAL] void CQtOpenCVCaptureObject::signal_ImageChanged ( const IplImage* value )
brief Сигнал оповещения об изменении указателя на изображение типа IplImage
библиотеки OpenCV.
param value - новый указатель на изображение типа IplImage библиотеки OpenCV.
*/
void signal_ImageChanged ( const IplImage* );
/**
fn [SIGNAL] void CQtOpenCVCaptureObject::signal_TimeoutChanged ()
brief Сигнал оповещения об изменении таймаута запроса изображения
*/
void signal_TimeoutChanged ();
/**
fn [SIGNAL] void CQtOpenCVCaptureObject::signal_TimeoutChanged ( int value )
brief Сигнал оповещения об изменении таймаута запроса изображения
param value - новое значение таймаута запроса изображения
*/
void signal_TimeoutChanged ( int );
/**
fn [SIGNAL] void CQtOpenCVCaptureObject::signal_ActiveChanged ( bool value )
brief Сигнал оповещения смены статуса активности запроса изображения от
устройства видеозахвата по тайм-ауту.
param value - новое значение активности процесса запроса. Значение true
говорит о выполнении, а false - об останове процесса запроса
по тайм-ауту.
*/
void signal_ActiveChanged ( bool );
public slots:
void slot_SetNumber ( int );
void slot_SetPath ( const QString& );
void slot_SetAsInternal ( bool );
void slot_SetTimeout ( int );
void slot_captureOn ( bool );
void slot_Activate (bool);
void slot_SetRecap (bool);
protected:
virtual
void timerEvent(QTimerEvent *event);
private:
Q_DISABLE_COPY(CQtOpenCVCaptureObject)
Q_DECLARE_PRIVATE(CQtOpenCVCaptureObject)
QScopedPointer<CQtOpenCVCaptureObjectPrivate> d_ptr;
};
/*----------------------------------------------------------------------------*/
QT_END_NAMESPACE
QT_END_HEADER
#endif // CQTOPENCVCAPTUREOBJECT_H
Слоты:
Жизнь научила ставить комментарии. Думаю, вам всё понятно.
В файле .pro
подключим библиотеки OpenCV
unix: LIBS += -L/usr/lib/ -lopencv_core -lopencv_highgui
INCLUDEPATH += /usr/include/opencv2/core
/usr/include/opencv2/highgui
DEPENDPATH += /usr/include/opencv2/core
/usr/include/opencv2/highgui
Всё. Библиотека создана. Проверим её работу.
Создадим графический интерфейс к нашему устройству видеозахвата. Зачем графический? Всё просто: мы используем его и компоненты форматирования при построении виджета в коллекции плагинов к Qt Designer.
Не буду утруждать рисунками, вы найдёте форму в каталоге examples проекта testCaptureRuntime
Укажем видеофайл:
Скорость кадров можно регулировать значением таймаута, «поиграйте» с ним.
Переключим на встроенную в компьютер камеру:
Переключим на внешнюю IP-камеру:
Библиотека работает.
Сегодня добавил в OpenCV поддержку камер Smartek Giganetix [3] на основе их GigEVisionSDK. Возможно, скоро выйдет, но я обязательно напишу в дальнейшем, как подключать своё устройство к списку видеозахвата OpenCV.
Здесь всё так же несложно, как и при создании биьблиотеки времени исполнения. Только «родитель» у класса QWidget, и прячем в приватный класс экземпляр нашего runtime класса.
В .pro
файл помещаем
DEFINES += QDESIGNER_EXPORT_WIDGETS
Больше нет необходимости подключать библиотеку OpenCV, она пойдёт по зависимости от runtime-библиотеки.
А, вот, её, родимую, и прикрутим:
unix: LIBS += -L/usr/lib -lQtOpenCVCapture
INCLUDEPATH += $$PWD/../../runtime/capture/QtOpenCVCapture
DEPENDPATH += /usr/lib
Обратите внимание! Путь указывает на /usr/lib
. Это удобно. В дальнейшем, просто создайте символическую ссылку на вашу библиотеку в этом каталоге, и не будет проблем с линковкой!
Объявим свойства виджета для дизайнера:
...
Q_PROPERTY(
bool visible
READ isVisible
WRITE slot_setVisible
)
Q_PROPERTY(
bool internal
READ isInternal
WRITE slot_SetAsInternal
)
Q_PROPERTY(
QString path
READ getPath
WRITE slot_SetPath
)
Q_PROPERTY(
int number
READ getNumber
WRITE slot_SetNumber
)
Q_PROPERTY(
int numberMax
READ getNumberMax
WRITE slot_SetNumberMax
)
Q_PROPERTY(
int timeout
READ getTimeoutInterval
WRITE slot_SetTimeout
)
Q_PROPERTY(
int timeoutMax
READ getTimeoutMax
WRITE slot_SetTimeoutMax
)
Q_PROPERTY(
int timeoutStep
READ getTimeoutStep
WRITE slot_SetTimeoutStep
)
Q_PROPERTY(
bool recapture
READ isRecap
WRITE slot_SetRecap
)
Q_PROPERTY(
QString FrameTitle
READ getFrameTitle
WRITE slot_setFrameTitle
)
Q_PROPERTY(
QString GroupBoxTitle
READ getGroupBoxTitle
WRITE slot_setGroupBoxTitle
)
Q_PROPERTY(
QString RadioNumberTitle
READ getRadioNumberTitle
WRITE slot_setRadioNumberTitle
)
Q_PROPERTY(
QString RadioPathTitle
READ getRadioPathTitle
WRITE slot_setRadioPathTitle
)
Q_PROPERTY(
QString PathTitle
READ getPathTitle
WRITE slot_setPathTitle
)
Q_PROPERTY(
QString NumberTitle
READ getNumberTitle
WRITE slot_setNumberTitle
)
Q_PROPERTY(
QString TimeOutTitle
READ getTimeOutTitle
WRITE slot_setTimeOutTitle
)
Q_PROPERTY(
QString TimeOutExtTitle
READ getTimeOutExtTitle
WRITE slot_setTimeOutExtTitle
)
Q_PROPERTY(
QString RecaptureTitle
READ getRecaptureTitle
WRITE slot_setRecaptureTitle
)
...
Расширим набор слотов и методов для поддержки свойств:
...
//собственные методы доступа
bool isVisible () const;
QString getFrameTitle () const;
QString getGroupBoxTitle () const;
QString getRadioNumberTitle () const;
QString getRadioPathTitle () const;
QString getPathTitle () const;
QString getNumberTitle () const;
QString getTimeOutTitle () const;
QString getTimeOutExtTitle () const;
QString getRecaptureTitle () const;
...
//собственные слоты
void slot_setVisible( bool );
void slot_setFrameTitle( const QString& );
void slot_setGroupBoxTitle( const QString& );
void slot_setRadioNumberTitle( const QString& );
void slot_setRadioPathTitle( const QString& );
void slot_setPathTitle( const QString& );
void slot_setNumberTitle( const QString& );
void slot_setTimeOutTitle( const QString& );
void slot_setTimeOutExtTitle( const QString& );
void slot_setRecaptureTitle( const QString& );
void slot_SetNumberMax ( int );
void slot_SetTimeoutMax ( int );
void slot_SetTimeoutStep ( int );
...
Скопируем настройки окна из тестового примера runtime- библиотеки:
/*----------------------------------------------------------------------------*/
void
CQtOpenCVCaptureWidgetPrivate::setupUi ( QWidget* parent )
{
p_Frame = new QFrame(parent);
Q_ASSERT(p_Frame);
p_Frame->setObjectName(QString::fromUtf8("p_Frame"));
p_Frame->resize(550, 195);
p_Frame->setMinimumSize(QSize(550, 195));
// p_Frame->setMaximumSize(QSize(550, 195));
p_Frame->setFrameShape(QFrame::StyledPanel);
p_Frame->setFrameShadow(QFrame::Raised);
p_gridLayout_Frame = new QGridLayout(p_Frame);
Q_ASSERT(p_gridLayout_Frame);
p_gridLayout_Frame->setObjectName(QString::fromUtf8("p_gridLayout_Frame"));
p_groupBox_Capture = new QGroupBox(p_Frame);
Q_ASSERT(p_groupBox_Capture);
p_groupBox_Capture->setObjectName(QString::fromUtf8("p_groupBox_Capture"));
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(p_groupBox_Capture->sizePolicy().hasHeightForWidth());
p_groupBox_Capture->setSizePolicy(sizePolicy);
// p_groupBox_Capture->setMinimumSize(QSize(540, 190));
// p_groupBox_Capture->setMaximumSize(QSize(540, 185));
p_groupBox_Capture->setFlat(true);
p_gridLayout_GBox = new QGridLayout(p_groupBox_Capture);
Q_ASSERT(p_gridLayout_GBox);
p_gridLayout_GBox->setSpacing(1);
p_gridLayout_GBox->setContentsMargins(3, 3, 3, 3);
p_gridLayout_GBox->setObjectName(QString::fromUtf8("p_gridLayout_GBox"));
p_horLayout_Radio = new QHBoxLayout();
Q_ASSERT(p_horLayout_Radio);
p_horLayout_Radio->setSpacing(1);
p_horLayout_Radio->setObjectName(QString::fromUtf8("p_horLayout_Radio"));
p_radioButton_URL = new QRadioButton(p_groupBox_Capture);
Q_ASSERT(p_radioButton_URL);
p_radioButton_URL->setObjectName(QString::fromUtf8("p_radioButton_URL"));
p_horLayout_Radio->addWidget(p_radioButton_URL);
p_radioButton_Number = new QRadioButton(p_groupBox_Capture);
Q_ASSERT(p_radioButton_Number);
p_radioButton_Number->setObjectName(QString::fromUtf8("p_radioButton_Number"));
p_radioButton_Number->setChecked(true);
p_horLayout_Radio->addWidget(p_radioButton_Number);
p_gridLayout_GBox->addLayout(p_horLayout_Radio, 0, 0, 1, 1);
p_horLayout_PathNum = new QHBoxLayout();
Q_ASSERT(p_horLayout_PathNum);
p_horLayout_PathNum->setSpacing(3);
p_horLayout_PathNum->setObjectName(QString::fromUtf8("p_horLayout_PathNum"));
p_label_PathNum = new QLabel(p_groupBox_Capture);
Q_ASSERT(p_label_PathNum);
p_label_PathNum->setObjectName(QString::fromUtf8("p_label_PathNum"));
QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Preferred);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
sizePolicy1.setHeightForWidth(p_label_PathNum->sizePolicy().hasHeightForWidth());
p_label_PathNum->setSizePolicy(sizePolicy1);
p_label_PathNum->setMinimumSize(QSize(150, 0));
p_label_PathNum->setLayoutDirection(Qt::LeftToRight);
p_label_PathNum->setFrameShape(QFrame::NoFrame);
p_label_PathNum->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter);
p_horLayout_PathNum->addWidget(p_label_PathNum);
p_spinBox_Number = new QSpinBox(p_groupBox_Capture);
Q_ASSERT(p_spinBox_Number);
p_spinBox_Number->setObjectName(QString::fromUtf8("p_spinBox_Number"));
sizePolicy.setHeightForWidth(p_spinBox_Number->sizePolicy().hasHeightForWidth());
p_spinBox_Number->setSizePolicy(sizePolicy);
p_spinBox_Number->setMinimum(0);
p_spinBox_Number->setMaximum(999999);
p_horLayout_PathNum->addWidget(p_spinBox_Number);
p_lineEdit = new QLineEdit(p_groupBox_Capture);
Q_ASSERT(p_lineEdit);
p_lineEdit->setObjectName(QString::fromUtf8("p_lineEdit"));
p_lineEdit->setEnabled(true);
p_horLayout_PathNum->addWidget(p_lineEdit);
p_gridLayout_GBox->addLayout(p_horLayout_PathNum, 1, 0, 1, 1);
p_horLayout_TOut = new QHBoxLayout();
Q_ASSERT(p_horLayout_TOut);
p_horLayout_TOut->setSpacing(3);
p_horLayout_TOut->setObjectName(QString::fromUtf8("p_horLayout_TOut"));
p_label_TOut = new QLabel(p_groupBox_Capture);
Q_ASSERT(p_label_TOut);
p_label_TOut->setObjectName(QString::fromUtf8("p_label_TOut"));
sizePolicy1.setHeightForWidth(p_label_TOut->sizePolicy().hasHeightForWidth());
p_label_TOut->setSizePolicy(sizePolicy1);
p_label_TOut->setMinimumSize(QSize(150, 0));
p_horLayout_TOut->addWidget(p_label_TOut);
p_spinBox_TOut = new QSpinBox(p_groupBox_Capture);
Q_ASSERT(p_spinBox_TOut);
p_spinBox_TOut->setObjectName(QString::fromUtf8("p_spinBox_TOut"));
sizePolicy.setHeightForWidth(p_spinBox_TOut->sizePolicy().hasHeightForWidth());
p_spinBox_TOut->setSizePolicy(sizePolicy);
p_spinBox_TOut->setMinimum(0);
p_spinBox_TOut->setMaximum(999999);
p_horLayout_TOut->addWidget(p_spinBox_TOut);
p_label_ms = new QLabel(p_groupBox_Capture);
Q_ASSERT(p_label_ms);
p_label_ms->setObjectName(QString::fromUtf8("p_label_ms"));
sizePolicy1.setHeightForWidth(p_label_ms->sizePolicy().hasHeightForWidth());
p_label_ms->setSizePolicy(sizePolicy1);
p_horLayout_TOut->addWidget(p_label_ms);
p_horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Preferred, QSizePolicy::Minimum);
Q_ASSERT(p_horizontalSpacer);
p_horLayout_TOut->addItem(p_horizontalSpacer);
p_gridLayout_GBox->addLayout(p_horLayout_TOut, 2, 0, 1, 1);
p_horLayout_Buttons = new QHBoxLayout();
Q_ASSERT(p_horLayout_Buttons);
p_horLayout_Buttons->setSpacing(3);
p_horLayout_Buttons->setObjectName(QString::fromUtf8("p_horLayout_Buttons"));
p_checkBox_Recap = new QCheckBox(p_groupBox_Capture);
Q_ASSERT(p_checkBox_Recap);
p_checkBox_Recap->setObjectName(QString::fromUtf8("p_checkBox_Recap"));
sizePolicy.setHeightForWidth(p_checkBox_Recap->sizePolicy().hasHeightForWidth());
p_checkBox_Recap->setSizePolicy(sizePolicy);
p_horLayout_Buttons->addWidget(p_checkBox_Recap);
p_pushButton_Test = new QPushButton(p_groupBox_Capture);
Q_ASSERT(p_pushButton_Test);
p_pushButton_Test->setObjectName(QString::fromUtf8("p_pushButton_Test"));
p_pushButton_Test->setCheckable(true);
p_pushButton_Test->setChecked(false);
p_horLayout_Buttons->addWidget(p_pushButton_Test);
p_gridLayout_GBox->addLayout(p_horLayout_Buttons, 3, 0, 1, 1);
p_gridLayout_Frame->addWidget(p_groupBox_Capture, 0, 0, 1, 1);
#ifndef QT_NO_SHORTCUT
p_label_PathNum->setBuddy(p_lineEdit);
#endif // QT_NO_SHORTCUT
retranslateUi();
QMetaObject::connectSlotsByName(p_Frame);
}
Подключим сигналы и слоты:
/*----------------------------------------------------------------------------*/
void
CQtOpenCVCaptureWidgetPrivate::setupConnections ()
{
// перенаправление сигналов runtime-объекта на выход виджета
q_obj->connect (q_obj, SIGNAL(signal_Errno(int,QString)), q_ptr, SIGNAL(signal_Errno(int,QString)));
q_obj->connect (q_obj, SIGNAL(signal_CaptureChanged()), q_ptr, SIGNAL(signal_CaptureChanged()));
q_obj->connect (q_obj, SIGNAL(signal_CaptureChanged(const CvCapture*)), q_ptr, SIGNAL(signal_CaptureChanged(const CvCapture*)));
q_obj->connect (q_obj, SIGNAL(signal_ImageChanged(const IplImage*)), q_ptr, SIGNAL(signal_ImageChanged(const IplImage*)));
q_obj->connect (q_obj, SIGNAL(signal_TimeoutChanged()), q_ptr, SIGNAL(signal_TimeoutChanged()));
q_obj->connect (q_obj, SIGNAL(signal_TimeoutChanged(int)), q_ptr, SIGNAL(signal_TimeoutChanged(int)));
q_obj->connect (q_obj, SIGNAL(signal_ActiveChanged(bool)), q_ptr, SIGNAL(signal_ActiveChanged(bool)));
// установка обработки переключения устройств получения видеоинформации
q_ptr->connect (p_radioButton_Number,SIGNAL(toggled(bool)), q_ptr, SLOT(slot_SetAsInternal(bool)));
q_ptr->connect (p_radioButton_URL, SIGNAL(toggled(bool)), q_ptr, SLOT(slot_SetAsExternal(bool)));
// обработка редактирования и ввода строки пути устроцства видеозахвата
q_ptr->connect (p_lineEdit, SIGNAL(textChanged(QString)), q_ptr, SLOT(slot_SetPath(QString)));
q_ptr->connect (p_lineEdit, SIGNAL(returnPressed()), q_ptr, SLOT(slot_PathComplete()));
// установка обработки изменения номера встроенной вебкамеры
q_ptr->connect (p_spinBox_Number, SIGNAL(valueChanged(int)), q_ptr, SLOT(slot_SetNumber(int)));
// установка обработки изменения тайм-аута опроса устройства
q_ptr->connect (p_spinBox_TOut, SIGNAL(valueChanged(int)), q_ptr, SLOT(slot_SetTimeout(int)));
// установка обработки изменения включения реинициализации устройства видеозахвата в каждом тайм-ауте
q_ptr->connect (p_checkBox_Recap, SIGNAL(toggled(bool)), q_ptr, SLOT(slot_SetRecap(bool)));
// установка обработки сигнала к тестированию
q_ptr->connect (p_pushButton_Test, SIGNAL(toggled(bool)), q_ptr, SLOT(slot_Test(bool)));
// q_ptr->connect (q_ptr, SIGNAL(signal_ImageChanged(const IplImage*)), q_ptr, SLOT(slot_ShowImage(const IplImage*)));
}
/*----------------------------------------------------------------------------*/
Собираем библиотеку на основе виджета.
Настало время подключить нашу QWidget-библиотеку к Qt Designer.
Создадим проект-коллекцию.
CONFIG += designer plugin debug_and_release
TARGET = $$qtLibraryTarget(CQtOpenCVCollection)
TEMPLATE = lib
DEFINES += QDESIGNER_EXPORT_WIDGETS
HEADERS = cqtopencvcapturewidgetplugin.h cqtopencvcollection.h
SOURCES = cqtopencvcapturewidgetplugin.cpp cqtopencvcollection.cpp
RESOURCES = icons.qrc
//target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += target
#include(cqtopencvimagewidget.pri)
include(cqtopencvcapturewidget.pri)
#include(cqtopencvcannywidget.pri)
unix: LIBS += -L/usr/lib/ -lQtOpenCVCaptureWidget
INCLUDEPATH += $$PWD/
DEPENDPATH += $$PWD/
Объявим класс плагина.
#ifndef CQTOPENCVCAPTUREWIDGETPLUGIN_H
#define CQTOPENCVCAPTUREWIDGETPLUGIN_H
#include <QDesignerCustomWidgetInterface>
#include <QtDesigner/QDesignerExportWidget>
class
#if defined(QDESIGNER_EXPORT_WIDGETS)
QDESIGNER_WIDGET_EXPORT
#else
Q_DECL_EXPORT
#endif
CQtOpenCVCaptureWidgetPlugin : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
CQtOpenCVCaptureWidgetPlugin(QObject *parent = 0);
bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget *createWidget(QWidget *parent);
void initialize(QDesignerFormEditorInterface *core);
private:
bool m_initialized;
};
Объявим класс коллекции:
#ifndef CQTOPENCVCOLLECTION_H
#define CQTOPENCVCOLLECTION_H
#include <QtDesigner/QtDesigner>
#include <QtCore/qplugin.h>
class CQtOpenCVCollection : public QObject, public QDesignerCustomWidgetCollectionInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)
public:
explicit CQtOpenCVCollection(QObject *parent = 0);
virtual QList<QDesignerCustomWidgetInterface*> customWidgets() const;
private:
QList<QDesignerCustomWidgetInterface*> m_widgets;
};
#endif
Реализация:
#include "cqtopencvcapturewidgetplugin.h"
//#include "cqtopencvimagewidgetplugin.h"
//#include "cqtopencvcannywidgetplugin.h"
#include "cqtopencvcollection.h"
CQtOpenCVCollection::CQtOpenCVCollection(QObject *parent)
: QObject(parent)
{
m_widgets.append(new CQtOpenCVCaptureWidgetPlugin(this));
// m_widgets.append(new CQtOpenCVImageWidgetPlugin(this));
// m_widgets.append(new CQtOpenCVCannyWidgetPlugin(this));
}
QList<QDesignerCustomWidgetInterface*> CQtOpenCVCollection::customWidgets() const
{
return m_widgets;
}
Q_EXPORT_PLUGIN2(CQtOpenCVCollection, CQtOpenCVCollection)
Обратите внимание на
// m_widgets.append(new CQtOpenCVImageWidgetPlugin(this));
// m_widgets.append(new CQtOpenCVCannyWidgetPlugin(this));
После реализаций плагинов CQtOpenCVImageWidgetPlugin
и CQtOpenCVCannyWidgetPlugin
комментарии можно будет убрать. И в группе OpenCV компонент Qt Designer появятся новые элементы.
Aрхива проекта. [2]
После сборки всех библиотек, корректного назначения ссылок и установки ссылки на коллекцию в каталог плагинов для Qt Designer можно создать тестовый пример.
В Дизайнере создаём MainWindow, помещаем наш виджет, собираем.
Видим:
Спасибо за внимание.
Автор: coffeesmoke
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/qt-2/12043
Ссылки в тексте:
[1] Qt Designer & Runtime Qt библиотеки на службе OpenCV...: http://habrahabr.ru/post/146210/
[2] архива проекта: http://www.wuala.com/coffeesmoke/development/C_CPP/Qt_and_OpenCV/files/QtOpenCVWidgets-20120725.zip
[3] Smartek Giganetix: http://www.smartekvision.com
Нажмите здесь для печати.