当前位置:网站首页>Custom plug-in construction and use of QT plug-in
Custom plug-in construction and use of QT plug-in
2022-07-03 16:16:00 【Manon Feifei】
List of articles
The last article introduced how to build Qt Designer plug-in unit . In fact, the plug-in mechanism QT It's open to the outside world , Here is how to use QT Develop custom plug-ins . Before developing a custom plug-in, we first define the plug-in SDK. The plug-in SDK Is the interface description of the plug-in , Any plug-in developed by developers should implement the corresponding interface . At the same time, as long as the plug-in of the corresponding interface is implemented , Can be integrated into the system , This actually provides a unified interface standard for custom plug-ins .
Define the SDK
Here we define the plug-in SDK, The implementation is as follows :
//sdk/MyPluginInterface.h
#ifndef MY_PLUGIN_INTERFACE_H
#define MY_PLUGIN_INTERFACE_H
#include <QWidget>
// Prevent naming conflicts by adding namespaces
namespace Plugin {
class MyPluginInterface
{
public:
virtual ~MyPluginInterface() {
}
// Name of the plug-in instance
virtual QString name() const = 0;
// establish UI Example
virtual QWidget* createWidget(QWidget* parent) = 0;
// Get the display name of the plug-in
virtual QString displayName() const = 0;
};
}
// Defined in the QT The globally unique interface in the system ID
// Realize the SDK The plug-in of should also define the same ID
// Interface ID Contains version information , Through the ID We can distinguish between different versions SDK And plug-ins
//Q_DECLARE_INTERFACE Macros will be of type and ID Connect , such QT You can verify whether the loaded plug-in can be converted into MyPluginInterface type
#define interface_iid "org.pluginqt.custompluginuse.myplugin.myplugin1.0.0"
Q_DECLARE_INTERFACE(Plugin::MyPluginInterface, interface_iid)
#endif
The plug-in SDK The plug-in interface is defined in QT Global in object system ID. At the same time, in order to prevent naming conflicts , We also added a namespace to the interface of the plug-in , Prevent naming conflicts in different environments .
Write a custom plug-in
First, create a new dynamic library project . The project configuration is as follows :
QT += core widgets
TARGET = $$qtLibraryTarget(custom-colorcombo-plugin)
TEMPLATE = lib
CONFIG += plugin
# Include the corresponding plug-ins SDK Catalog
INCLUDEPATH += $$PWD/sdk
DEPENDPATH += $$PWD/sdk
# Specify the output path
debug:DESTDIR = $$PWD/../CustomPlugin_output/debug/
release:DESTDIR =$$PWD/../CustomPlugin_output/release/
SOURCES += \
customplugin.cpp \
colorcombox.cpp
HEADERS += \
customplugin.h \
colorcombox.h
# add to SDK file
OTHER_FILES += \
sdk/MyPluginInterface.h \
After creating the plug-in project , Write with QT Designer The plug-in is the same , Add one inherited from MyPluginInterface and QObject Class plug-in information description class , The plug-in ID Should be and SDK Medium ID bring into correspondence with . The specific implementation is as follows :
//customplugin.h
#ifndef CUSTOMPLUGIN_H
#define CUSTOMPLUGIN_H
#include "sdk/MyPluginInterface.h"
#include <QObject>
class CustomPlugin : public QObject, Plugin::MyPluginInterface
{
Q_OBJECT
// Statement QT Unique identifier of the identification
// and SDK Medium ID bring into correspondence with
Q_PLUGIN_METADATA(IID "org.pluginqt.custompluginuse.myplugin.myplugin1.0.0")
// Declare the implemented plug-in interface
Q_INTERFACES(Plugin::MyPluginInterface)
public:
CustomPlugin(QObject* parent = 0);
QString name() const override;
QWidget* createWidget(QWidget* parent) override;
QString displayName() const override;
};
#endif // CUSTOMPLUGIN_H
//customplugin.cpp
#include "customplugin.h"
#include "colorcombox.h"
CustomPlugin::CustomPlugin(QObject *parent):QObject(parent)
{
}
QString CustomPlugin::name() const
{
return "colorCombox";
}
QWidget* CustomPlugin::createWidget(QWidget* parent)
{
return new ColorComboBox(parent);
}
QString CustomPlugin::displayName() const
{
return " Used to select colors ";
}
The plug-in is responsible for loading a user-defined control , Here, the color drop-down list control is also taken as an example , The specific implementation is as follows :
//colorcombox.h
#ifndef COLORCOMBOBOX_H
#define COLORCOMBOBOX_H
#include <QComboBox>
class ColorComboBox : public QComboBox
{
Q_OBJECT
public:
explicit ColorComboBox(QWidget *parent = 0);
private slots:
void slot_currentIndexChanged(int index);
public:
bool getShowColorName();
QString getColorName();
public slots:
void setShowColorName(bool showColorName);
void setColorName(QString colorName);
void initColorItems();
signals:
// Name and color change signal
void colorChanged(QString colorName);
void colorChanged(QColor color);
private:
// Whether to display English name
bool menableColorName;
// Current color name
QString mcolorName;
};
#endif // COLORCOMBOBOX_H
//colorcombox.cpp
#include "colorcombox.h"
ColorComboBox::ColorComboBox(QWidget *parent) : QComboBox(parent),
menableColorName(true)
{
initColorItems();
connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(slot_currentIndexChanged(int)));
}
void ColorComboBox::slot_currentIndexChanged(int index)
{
if (index >= 0)
{
mcolorName = QColor::colorNames().at(index);
emit colorChanged(mcolorName);
emit colorChanged(QColor(mcolorName));
}
}
bool ColorComboBox::getShowColorName()
{
return menableColorName;
}
QString ColorComboBox::getColorName()
{
return mcolorName;
}
void ColorComboBox::setShowColorName(bool showColorName)
{
if (menableColorName != showColorName) {
menableColorName = showColorName;
}
}
void ColorComboBox::setColorName(QString colorName)
{
if (mcolorName != colorName)
{
mcolorName = colorName;
int index = QColor::colorNames().indexOf(colorName);
this->setCurrentIndex(index);
}
}
void ColorComboBox::initColorItems()
{
clear();
QStringList colorList = QColor::colorNames();
for(QString strColor: colorList)
{
QPixmap pix(this->iconSize());
pix.fill(strColor);
this->addItem(QIcon(pix), menableColorName ? strColor : "");
}
}
Dynamically load custom plug-ins
After writing the custom plug-in , We can use QPluginLoader Dynamically load custom plug-ins . adopt QPluginLoader Class loading plug-ins , It can automatically check the of writing plug-ins QT Version and write the main application QT Version consistency , At the same time through instance() You can directly convert plug-in objects into QObject object .
When loading plug-ins , We can also pass QPluginLoader Get plug-in METADATA, Then according to different Q_PLUGIN_METADATA Perform different actions . In this way, the main application can be compatible with different versions of plug-ins .
An example of dynamically loading plug-ins in the main application is shown below :
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
public slots:
void slot_load_plugin();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
//widget.cpp
#pragma execution_character_set("utf-8")
#include "ui_widget.h"
#include "sdk/MyPluginInterface.h"
#include <QFileDialog>
#include <QPluginLoader>
#include <QHBoxLayout>
#include <memory>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->load_plugin_btn,SIGNAL(clicked(bool)),this, SLOT(slot_load_plugin()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::slot_load_plugin()
{
QString file_path = QFileDialog::getOpenFileName(NULL," Add plug-ins ","../cutomplugin_output","dll (*.dll *.so)");
if(file_path.isEmpty())
{
return;
}
QPluginLoader pluginLoader(file_path);
QObject* plugin = pluginLoader.instance();
if (plugin) {
std::unique_ptr<Plugin::MyPluginInterface> interface_ptr = std::unique_ptr<Plugin::MyPluginInterface>(qobject_cast<Plugin::MyPluginInterface*>(plugin));
QWidget* widget = interface_ptr->createWidget(this);
widget->setFixedHeight(40);
widget->setFixedWidth(200);
QHBoxLayout* mainLayout = new QHBoxLayout(this);
mainLayout->addWidget(widget);
ui->widget->setLayout(mainLayout);
}
}
The dynamic loading effect of custom plug-ins is as follows :
distribution SDK
Define the plug-in SDK after , We can SDK Distribute to plug-in developers . As long as the plug-in developed by the plug-in developer realizes the corresponding SDK Interface , Then the developed plug-ins can be integrated into the corresponding system . In this way, plug-in development and main application development are completely decoupled . Developers do not need to know the details of the main application to develop plug-ins that can be integrated into the main application .
Reference examples
link :https://pan.baidu.com/s/1HoG3OAAyEbozs7CshH0B1w
Extraction code :vt3x
边栏推荐
- Page dynamics [2]keyframes
- Go语言自学系列 | golang中的if else语句
- SDNU_ ACM_ ICPC_ 2022_ Winter_ Practice_ 4th [individual]
- The accept attribute of the El upload upload component restricts the file type (detailed explanation of the case)
- Brush questions -- sword finger offer
- Is it safe to open an account with flush?
- NFT新的契机,多媒体NFT聚合平台OKALEIDO即将上线
- Nifi from introduction to practice (nanny level tutorial) - flow
- 一些事情的反思
- [combinatorics] combinatorial identities (sum of variable terms 3 combinatorial identities | sum of variable terms 4 combinatorial identities | binomial theorem + derivation to prove combinatorial ide
猜你喜欢

Record a jar package conflict resolution process

远程文件包含实操

几种常见IO模型的原理

Famous blackmail software stops operation and releases decryption keys. Most hospital IOT devices have security vulnerabilities | global network security hotspot on February 14
![[statement] about searching sogk1997 and finding many web crawler results](/img/1a/8ed3ca0030ea227adcd95e8b306aca.png)
[statement] about searching sogk1997 and finding many web crawler results

nifi从入门到实战(保姆级教程)——flow

Slam learning notes - build a complete gazebo multi machine simulation slam from scratch (II)

How to thicken the brush in the graphical interface

Uploads labs range (with source code analysis) (under update)

Détails du contrôle de la congestion TCP | 3. Espace de conception
随机推荐
Remote file contains actual operation
Detailed explanation of four modes of distributed transaction (Seata)
Qt插件之自定义插件构建和使用
SVN使用规范
分布式事务(Seata) 四大模式详解
Thinking about telecommuting under the background of normalization of epidemic | community essay solicitation
Slam learning notes - build a complete gazebo multi machine simulation slam from scratch (II)
"Everyday Mathematics" serial 56: February 25
Détails du contrôle de la congestion TCP | 3. Espace de conception
请做好3年内随时失业的准备?
nifi从入门到实战(保姆级教程)——flow
How idea starts run dashboard
相同切入点的抽取
Mixlab编辑团队招募队友啦~~
"Remake Apple product UI with Android" (2) -- silky Appstore card transition animation
Microservice - fuse hystrix
How to use AAB to APK and APK to AAB of Google play apps on the shelves
The mixlab editing team is recruiting teammates~~
Shell script import and export data
Redis高可用与持久化