当前位置:网站首页>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
边栏推荐
- Shell script import and export data
- Is it safe to open an account with tongdaxin?
- [redis foundation] understand redis persistence mechanism together (rdb+aof graphic explanation)
- Slam learning notes - build a complete gazebo multi machine simulation slam from scratch (III)
- Intelij idea efficient skills (III)
- EditText request focus - EditText request focus
- Principles of several common IO models
- Expression of request header in different countries and languages
- 切入点表达式
- Go language self-study series | if else statement in golang
猜你喜欢

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

MB10M-ASEMI整流桥MB10M

How can technology managers quickly improve leadership?
![[proteus simulation] 74hc595+74ls154 drive display 16x16 dot matrix](/img/d6/3c21c25f1c750f17aeb871124e80f4.png)
[proteus simulation] 74hc595+74ls154 drive display 16x16 dot matrix

Shell script import and export data

TCP擁塞控制詳解 | 3. 設計空間
![[redis foundation] understand redis persistence mechanism together (rdb+aof graphic explanation)](/img/68/3721975cf33fcfacc28dc4d3d6a5ca.jpg)
[redis foundation] understand redis persistence mechanism together (rdb+aof graphic explanation)

深入理解 SQL 中的 Grouping Sets 语句

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

近视:摘镜or配镜?这些问题必须先了解清楚
随机推荐
The difference between calling by value and simulating calling by reference
Qt插件之自定义插件构建和使用
Approval process design
【声明】关于检索SogK1997而找到诸多网页爬虫结果这件事
Microservice sentinel flow control degradation
Why does the std:: string operation perform poorly- Why do std::string operations perform poorly?
Redis installation under windows and Linux systems
Reflection on some things
Golang 匿名函数使用
Go语言自学系列 | golang中的if else if语句
[web security] - [SQL injection] - error detection injection
Pyinstaller is not an internal or external command, nor is it a runnable program or batch file
一些事情的反思
MB10M-ASEMI整流桥MB10M
Microservice API gateway
App mobile terminal test [3] ADB command
How to initialize views when loading through storyboards- How is view initialized when loaded via a storyboard?
高等数学(第七版)同济大学 习题2-1 个人解答
Microservices Seata distributed transactions
阿飞的期望