воскресенье, 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 рядом в программой, использующий данный плагин