Справочная документация по Qt

Оглавление

Как создать подключаемые модули Qt (Qt plugins)

Qt предлагает два API для создания подключаемых модулей (plugins) :

Например, если вы хотите написать собственный подкласс QStyle и заставить приложение на Qt загружать его динамически, вы будете использовать высокоуровневое API.

Так как высокоуровневое API построено на низкоуровневом API, некоторые особенности общие для обоих.

Если вы хотите предоставить подключаемые модули для использования вместе с Qt Designer, смотрите документацию модуля QtDesigner.

Темы:

Высокоуровневое API: Написание расширений для Qt

Написание подключаемого модуля, который расширяет Qt, достигается наследованием соответствующего базового класса подключаемого модуля, реализацией нескольких функции, и добавлением макроса.

Есть несколько базовых классов подключаемых модулей. Вторичные подключаемые модули, по умолчанию, хранятся в подкаталогах стандартного каталога подключаемых модулей. Qt не найдет подключаемые модули, если они не хранятся в правильном каталоге.

Базовый классИмя директорииЧувствительность к регистру
QAccessibleBridgePluginaccessiblebridgeЧувствителен к регистру
QAccessiblePluginaccessibleЧувствителен к регистру
QDecorationPlugindecorationsНечувствителен к регистру
QFontEnginePluginfontenginesНечувствителен к регистру
QIconEnginePluginiconenginesНечувствителен к регистру
QImageIOPluginimageformatsЧувствителен к регистру
QInputContextPlugininputmethodsЧувствителен к регистру
QKbdDriverPluginkbddriversНечувствителен к регистру
QMouseDriverPluginmousedriversНечувствителен к регистру
QScreenDriverPlugingfxdriversНечувствителен к регистру
QScriptExtensionPluginscriptЧувствителен к регистру
QSqlDriverPluginsqldriversЧувствителен к регистру
QStylePluginstylesНечувствителен к регистру
QTextCodecPlugincodecsЧувствителен к регистру

Предположим, что у вас есть новый класс стиля, названый MyStyle, который вы хотите сделать доступным в качестве подключаемого модуля. Требуемый код очень простой, вот объявление класса (mystyleplugin.h):

 class MyStylePlugin : public QStylePlugin
 {
 public:
     QStringList keys() const;
     QStyle *create(const QString &key);
 };

Убедитесь, что реализация класса расположена в файле .cpp (включая объявление класса):

 #include "mystyleplugin.h"

 QStringList MyStylePlugin::keys() const
 {
     return QStringList() << "MyStyle";
 }

 QStyle *MyStylePlugin::create(const QString &key)
 {
     if (key.toLower() == "mystyle")
         return new MyStyle;
     return 0;
 }

 Q_EXPORT_PLUGIN2(pnp_mystyleplugin, MyStylePlugin)

(Заметьте, что QStylePlugin не чувствителен к регистру и использована прописная версия ключа в нашей реализации create(); большинство других подключаемых модулей чувствительны к регистру.)

Для драйверов баз данных, форматов изображений, текстовых кодеков и большинства других типов подключаемых модулей, не требуется явное создание объекта. Qt найдет и создаст их как требуется. Исключением являются стили, так как вы можете хотеть установить стиль в коде, явно. Чтобы добавить стиль, используйте следующий код:

 QApplication::setStyle(QStyleFactory::create("MyStyle"));

Некоторые классы подключаемых модулей требуют реализации дополнительных функций. За подробностями о виртуальных функциях, которые должны быть переопределены для каждого типа подключаемого модуля, обращайтесь к документации классов.

Пример "Style Plugin" показывает, как реализовать подключаемый модуль, который расширяет базовый класс QStylePlugin.

Низкоуровневое API: Расширение приложений на Qt

Не только сама Qt, но так же приложения на Qt могут быть расширены с помощью подключаемых модулей. Это требует от приложения обнаружить и загрузить подключаемые модули используя QPluginLoader. В этом случае, подключаемые модули могут предоставлять произвольную функциональность и не ограничены драйверами баз данных, форматами изображений, текстовыми кодеками, стилями, и другими типами подключаемых модулей, которые расширяют функциональность Qt.

Создание расширяемых с помощью подключаемых модулей приложений включает следующие шаги:

  1. Определите набор интерфейсов (классов с чисто виртуальными функциями), используемыми для общения с подключаемыми модулями.
  2. Используйте макрос Q_DECLARE_INTERFACE(), чтобы сообщить метаобъектной системе Qt об интерфейсе.
  3. Используйте QPluginLoader, в приложениях, для загрузки подключаемых модулей.
  4. Используйте qobject_cast(), чтобы определить, реализует ли подключаемый модуль данный интерфейс.

Написание подключаемого модуля включает следующие шаги:

  1. Объявите класс подключаемого модуля, который унаследован от QObject и от интерфейсов, которые этот подключаемый модуль хочет предоставить.
  2. Используйте макрос Q_INTERFACES(), чтобы сообщить метаобъектной системе Qt об интерфейсах.
  3. Экспортируйте подключаемый модуль, используя макрос Q_EXPORT_PLUGIN2().
  4. Соберите подключаемый модуль с помощью подходящего .pro-файла.

Например, вот определение интерфейсного класса:

 class FilterInterface
 {
 public:
     virtual ~FilterInterface() {}

     virtual QStringList filters() const = 0;
     virtual QImage filterImage(const QString &filter, const QImage &image,
                                QWidget *parent) = 0;
 };

Вот определение класса подключаемого модуля, который реализует этот интерфейс:

 #include <QObject>
 #include <QStringList>
 #include <QImage>

 #include <plugandpaint/interfaces.h>

 class ExtraFiltersPlugin : public QObject, public FilterInterface
 {
     Q_OBJECT
     Q_INTERFACES(FilterInterface)

 public:
     QStringList filters() const;
     QImage filterImage(const QString &filter, const QImage &image,
                        QWidget *parent);
 };

Документация примера "Plug & Paint" объясняет этот процесс в подробностях. Смотрите также Создание собственных виджетов для Qt Designer, для получения информации о проблемах, специфичных для Qt Designer. Вы можете так же взглянуть на Пример "Echo Plugin" - наиболее простой пример того, как реализовать подключаемый модуль, расширяющий приложение на Qt. Пожалуйста, обратите внимание на то, что QCoreApplication должен быть инициализирован до загрузки подключаемых модулей.

Размещение подключаемых модулей

Приложения на Qt автоматически знают какие подключаемые модули доступны, так как они хранятся в стандартных каталогах подключаемых модулей. Из-за этого приложению не требуется код для поиска и загрузки подключаемых модулей, так как Qt управляет ими автоматически.

Во время разработки, каталог для подключаемых модулей это QTDIR/plugins (где QTDIR то каталог, где установлена Qt), с подкаталогом для каждого типа подключаемых модулей, например, styles. Если вы хотите, чтобы ваше приложение использовало подключаемые модули и вы не хотите использовать стандартный путь к подключаемым модулям, заставьте ваш инсталляционный процесс определить путь, который вы хотите использовать для подключаемых модулей и сохраните его, например, используя QSettings, для считывания приложением при запуске. Приложение может вызвать QCoreApplication::addLibraryPath() с этим путем и ваши подключаемые модули будут доступны приложению. Заметьте, что последняя часть пути (например, styles) не может быть изменена.

Если вы хотите, чтобы подключаемый модуль был загружаемым, тогда единственный подход - это создать подкаталог в папке с программой и положить подключаемый модуль в этот каталог. Если вы распространяете любые подключаемые модули, которые идут вместе с Qt (располагаются в каталоге plugins), вы должны скопировать подкаталог ниже plugins, в котором расположен подключаемый модуль, в корневую папку вашего приложения (т.е., не добавлять каталог plugins).

Замечание: На Symbian все бинарные файлы должны располагать в каталоге \sys\bin, поэтому все подключаемые модули Qt имеют заглушку с таким же, что и у dll подключаемого модуля, базовым именем и суффиксом ".qtplugin", чтобы заставить подключаемые модули расширения Qt работать так же как и на других платформах. При попытке обнаружить подключаемый модуль, Qt фактически ищет заглушку взамен бинарного файла подключаемого модуля. До тех пор, пока файл-заглушка подключаемого модуля имеет суффикс ".qtplugin", они могут загружаться также по задаваемому имени файла со стандартным суффиксом библиотек ".dll" для QPluginLoader, поэтому обычно разработчику приложению не нужно беспокоиться о другом суффиксе заглушки. Из-за способа установки приложений в ROM или на различные другие диски в Symbian, Qt ищет заглушку в таком каталоге на всех доступных дисках, если она не расположена в заданном каталоге при загрузке подключаемого модуля.

Для получения дополнительной информации относительно развертывания, смотрите документацию Развёртывание приложений на Qt и Развёртывание подключаемых модулей.

Статические подключаемые модули

Обычный и наиболее гибкий способ добавления подключаемого модуля в приложение - это скомпилировать его в динамическую библиотеку, которая поставляется отдельно, и обнаруживать и загружать ее во время выполнения.

Подключаемые модули могут быть слинкованы статически вместе с приложением. Если вы соберете статическую версию Qt, то возможно включение только предопределенных подключаемых модулей Qt. Использование статических подключаемых модулей делает развёртывание менее подверженным ошибкам, но имеет то неудобство, что никакая функциональность из подключаемого модуля не может быть добавлена без полной повторной сборки и повторной распространения приложения.

Когда компилируется как статическая библиотека, тогда Qt предоставляет следующие статические подключаемые модули:

Имя подключаемого модуляТипОписание
qtaccessiblecompatwidgetsСпециальные возможностиСпециальные возможности для поддержки виджетов Qt 3
qtaccessiblewidgetsСпециальные возможностиСпециальные возможности для виджетов Qt
qdecorationdefaultДекорации (Выпуск Qt Extended)Стиль по умолчанию
qdecorationwindowsДекорации (Выпуск Qt Extended)Стиль Windows
qgifФорматы изображенийGIF
qjpegФорматы изображенийJPEG
qmngФорматы изображенийMNG
qicoФорматы изображенийICO
qsvgФорматы изображенийSVG
qtiffФорматы изображенийTIFF
qimsw_multiМетоды ввода (Выпуск Qt Extended)Переключатель метода ввода
qwstslibmousehandlerДрайвер мыши (Выпуск Qt Extended)мышь tslib
qgfxtransformedГрафические драйверы (Выпуск Qt Extended)Трансформированный экран
qgfxvncГрафические драйверы (Выпуск Qt Extended)VNC
qscreenvfbГрафические драйверы (Выпуск Qt Extended)Виртуальный видеобуфер (frame buffer)
qsqldb2драйвер SQLIBM DB2
qsqlibaseдрайвер SQLBorland InterBase
qsqliteдрайвер SQLSQLite версии 3
qsqlite2драйвер SQLSQLite версии 2
qsqlmysqlдрайвер SQLMySQL
qsqlociдрайвер SQLOracle (OCI)
qsqlodbcдрайвер SQLOpen Database Connectivity (ODBC)
qsqlpsqlдрайвер SQLPostgreSQL
qsqltdsдрайвер SQLSybase Adaptive Server (TDS)
qcncodecsТекстовый кодекУпрощенный китайский (Китайская народная республика)
qjpcodecsТекстовый кодекЯпонский
qkrcodecsТекстовый кодекКорейский
qtwcodecsТекстовый кодекТрадиционный китайский (Тайвань)

Чтобы линковать статически вместе с этими подключаемыми модулями, вам необходимо использовать макрос Q_IMPORT_PLUGIN() в своем приложении и вам необходимо добавить требуемые подключаемые модули к вашей сборке используя QTPLUGIN. Например, в вашем main.cpp:

 #include <QApplication>
 #include <QtPlugin>

 Q_IMPORT_PLUGIN(qjpeg)
 Q_IMPORT_PLUGIN(qgif)
 Q_IMPORT_PLUGIN(qkrcodecs)

 int main(int argc, char *argv[])
 {
     QApplication app(argc, argv);
     ...
     return app.exec();
 }

В .pro-файле вашего приложения, вам необходимо добавить следующую запись:

 QTPLUGIN     += qjpeg \
                 qgif \
                 qkrcodecs

Так же возможно создать свой собственный статический подключаемый модуль, следуя этим шагам:

  1. Добавьте CONFIG += static в ваш .pro-файл подключаемого модуля.
  2. Используйте макрос Q_IMPORT_PLUGIN() в вашем приложении.
  3. Линкуйте ваше приложение с библиотекой вашего подключаемого модуля используя LIBS в .pro-файле.

За подробностями, как это сделать, обращайтесь к примеру Plug & Paint и связанным с ним подключаемым модулем Basic Tools.

Замечание: Если вы не используете qmake для сборки вашего приложения, вам необходимо убедиться, что определен макрос препроцессора QT_STATICPLUGIN.

Развёртывание и отладка подключаемых модулей

Документ Развёртывание подключаемых модулей охватывает процесс развёртывания подключаемых модулей с приложениями и их отладку при возникновении проблем.

Смотрите также QPluginLoader, QLibrary и Пример "Plug & Paint".