воскресенье, 7 марта 2010 г.

Создание собственных виджетов с интеграцией в Qt Designer (Custom widget plugin)

В данном посте я создам виджет,а именно, в нем будет присутствовать QListWidget, кнопки перемещения элемента списка на позицию вверх и вниз, кнопка удаления. Так же в нем присутствует метод привязки данных и добавления отдельного элемента (QString). Такой элемент управления мне понадобился на одном из проектов, причем в нескольких местах, поэтому, я решил оформить его именно как отдельный элемент управления (User Control в .NET). Я не буду приводить код релизации виджета. Вместо этого сконцентрируемся на написании кода, необходимого для оформления виджета как плагина и успешной интеграции в Qt Designer и Qt Creator

Для начала создадим Qt GUI проект. Лично я сначала делаю это в Qt Creator, а потом генерирую проект для Visual Studio 2008 с помощью интегратора.
Поместим на форму QListWidget, три QPushButton, QLabel и скомпилируем и запустим проект. Видим, что все, что мы поместили на форму, отобразилось так, как мы и хотели. Теперь надо оформить все это в плагин.

В Qt Creator выбираем проект пользовательского виджета (в VS2008 - Qt4 Designer plugin).
Допустим в прошлом проекте у нас класс назывался ExtendedListWidget. В проекте плагина укажем такое же имя класса. Получим 4 файла
  • ExtendedListWidget.h
  • ExtendedListWidget.cpp
  • ExtendedListWidgetplugin.h
  • ExtendedListWidgetplugin.cpp

Содержимое *.pro-файла должно быть примерно таким:
CONFIG += designer plugin debug_and_release
TARGET = $$qtLibraryTarget($$TARGET)
TEMPLATE = lib
QT += svg
QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/designer
HEADERS = extendedlistwidgetplugin.h \
ui_extendedlistwidget.h \
extendedlistwidget.h

SOURCES = extendedlistwidgetplugin.cpp \
extendedlistwidget.cpp
RESOURCES = icons.qrc

# install
target.path = $$[QT_INSTALL_PLUGINS]/designer
sources.files = $$SOURCES $$HEADERS *.pro
sources.path = $$[QT_INSTALL_EXAMPLES]/designer/extendedlistwidgetplugin
INSTALLS += target sources

Заменяем ExtendedListWidget.h и ExtendedListWidget.cpp на одноименные файлы из предыдущего проекта.

Чтобы избавиться от сообщений типа
warning C4273: 'staticMetaObject' : inconsistent dll linkage
в заголовке ExtendedListWidget.h пишем макрос перед именем класса

#include<qtdesigner/qdesignerexportwidget> 
class QDESIGNER_WIDGET_EXPORT ExtendedListWidget: public QWidget
{
//......
}
Сами заголовочные файлы добавлять в файл проекта не надо, иначе рискуем получить что-то типа
path/to/program/release/moc_analogclock.cpp:40: error: ExtendedListWidget::staticMetaObject' : definition of dllimport static data member not allowed
Заголовочные файлы нужно просто поместить туда, где они смогут быть найденными препроцессором. Например, рядом с исходниками плагина.
Запускаем, получаем ExtendedListWidgetplugin.dll (нужна release), потому как Qt Creator и Qt Designer собраны (как правило) в release mode.
  • Помещаем полученную библиотеку в $(QTDIR)\..\bin\designer (для Qt Creator)
  • В $(QTDIR)\plugins\designer помещаем libExtendedListWidgetplugin.dll и libExtendedListWidgetplugin.lib (для Qt Designer)
  • А также помещаем libExtendedListWidgetplugin.dll рядом в программой, использующий данный плагин

5 комментариев :

vadun комментирует...

QT - Apple's Quick Time
Qt - cross-platform framework

Попробуйте найти на qt.nokia.com хоть один раз написание "QT".

Руслан комментирует...

Спасибо большое! Исправил, только вот ярлыки внизу не хотят исправляться.

dzx9 комментирует...

Можете описать последовательность действий, чтобы созданный плагин загружался в программу статически и не требовал .dll файла рядом с запускаемым .exe?

Руслан комментирует...

2dx9
Для начала надо собрать Qt статически, далее смотрим документацию http://qt-project.org/doc/qt-4.8/plugins-howto.html#static-plugins

alexey11111 комментирует...

Сделал плагин в VS2010 как было сказано. В дизайнере плагин доступен, но когда собираю проект, то получаю ошибку error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall SampleView::SampleView(class QWidget *)" (??0SampleView@@QAE@PAVQWidget@@@Z) в функции "public: void __thiscall Ui_SAMPLERClass::setupUi(class QMainWindow *)" (?setupUi@Ui_SAMPLERClass@@QAEXPAVQMainWindow@@@Z)

Что тут может быть?