$szTitle = "Qt 4.7: Как создать подключаемые модули Qt (Qt plugins)"; include "../_header47x.inc"; ?>
Qt предлагает два API для создания подключаемых модулей (plugins) :
Например, если вы хотите написать собственный подкласс QStyle и заставить приложение на Qt загружать его динамически, вы будете использовать высокоуровневое API.
Так как высокоуровневое API построено на низкоуровневом API, некоторые особенности общие для обоих.
Если вы хотите предоставить подключаемые модули для использования вместе с Qt Designer, смотрите документацию модуля QtDesigner.
Темы:
Написание подключаемого модуля, который расширяет Qt, достигается наследованием соответствующего базового класса подключаемого модуля, реализацией нескольких функции, и добавлением макроса.
Есть несколько базовых классов подключаемых модулей. Вторичные подключаемые модули, по умолчанию, хранятся в подкаталогах стандартного каталога подключаемых модулей. Qt не найдет подключаемые модули, если они не хранятся в правильном каталоге.
Базовый класс | Имя директории | Чувствительность к регистру |
---|---|---|
QAccessibleBridgePlugin | accessiblebridge | Чувствителен к регистру |
QAccessiblePlugin | accessible | Чувствителен к регистру |
QDecorationPlugin | decorations | Нечувствителен к регистру |
QFontEnginePlugin | fontengines | Нечувствителен к регистру |
QIconEnginePlugin | iconengines | Нечувствителен к регистру |
QImageIOPlugin | imageformats | Чувствителен к регистру |
QInputContextPlugin | inputmethods | Чувствителен к регистру |
QKbdDriverPlugin | kbddrivers | Нечувствителен к регистру |
QMouseDriverPlugin | mousedrivers | Нечувствителен к регистру |
QScreenDriverPlugin | gfxdrivers | Нечувствителен к регистру |
QScriptExtensionPlugin | script | Чувствителен к регистру |
QSqlDriverPlugin | sqldrivers | Чувствителен к регистру |
QStylePlugin | styles | Нечувствителен к регистру |
QTextCodecPlugin | codecs | Чувствителен к регистру |
Предположим, что у вас есть новый класс стиля, названый 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.
Не только сама Qt, но так же приложения на Qt могут быть расширены с помощью подключаемых модулей. Это требует от приложения обнаружить и загрузить подключаемые модули используя QPluginLoader. В этом случае, подключаемые модули могут предоставлять произвольную функциональность и не ограничены драйверами баз данных, форматами изображений, текстовыми кодеками, стилями, и другими типами подключаемых модулей, которые расширяют функциональность Qt.
Создание расширяемых с помощью подключаемых модулей приложений включает следующие шаги:
Написание подключаемого модуля включает следующие шаги:
Например, вот определение интерфейсного класса:
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 | драйвер SQL | IBM DB2 |
qsqlibase | драйвер SQL | Borland InterBase |
qsqlite | драйвер SQL | SQLite версии 3 |
qsqlite2 | драйвер SQL | SQLite версии 2 |
qsqlmysql | драйвер SQL | MySQL |
qsqloci | драйвер SQL | Oracle (OCI) |
qsqlodbc | драйвер SQL | Open Database Connectivity (ODBC) |
qsqlpsql | драйвер SQL | PostgreSQL |
qsqltds | драйвер SQL | Sybase 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
Так же возможно создать свой собственный статический подключаемый модуль, следуя этим шагам:
За подробностями, как это сделать, обращайтесь к примеру Plug & Paint и связанным с ним подключаемым модулем Basic Tools.
Замечание: Если вы не используете qmake для сборки вашего приложения, вам необходимо убедиться, что определен макрос препроцессора QT_STATICPLUGIN.
Документ Развёртывание подключаемых модулей охватывает процесс развёртывания подключаемых модулей с приложениями и их отладку при возникновении проблем.
Смотрите также QPluginLoader, QLibrary и Пример "Plug & Paint".