当前位置:网站首页>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
边栏推荐
- Go语言自学系列 | golang switch语句
- Q2 encryption market investment and financing report in 2022: gamefi becomes an investment keyword
- "Remake Apple product UI with Android" (3) - elegant statistical chart
- Détails du contrôle de la congestion TCP | 3. Espace de conception
- Is it safe to open an account with tongdaxin?
- Mb10m-asemi rectifier bridge mb10m
- How to use AAB to APK and APK to AAB of Google play apps on the shelves
- Go语言自学系列 | golang中的if else语句
- [redis foundation] understand redis master-slave architecture, sentinel mode and cluster together (Demo detailed explanation)
- Asemi rectifier bridge umb10f parameters, umb10f specifications, umb10f package
猜你喜欢
[system safety] 43 PowerShell malicious code detection series (5) automatic extraction of ten thousand words from abstract syntax tree
嵌入式开发:避免开源软件的7个理由
TCP拥塞控制详解 | 3. 设计空间
SDNU_ ACM_ ICPC_ 2022_ Winter_ Practice_ 4th [individual]
Mongodb installation and basic operation
"Remake Apple product UI with Android" (3) - elegant statistical chart
【OpenCV 例程200篇】217. 鼠标交互获取多边形区域(ROI)
How can technology managers quickly improve leadership?
TCP擁塞控制詳解 | 3. 設計空間
Microservice - Nacos registration center and configuration center
随机推荐
pyinstaller不是内部或外部命令,也不是可运行的程序 或批处理文件
[combinatorics] combinatorial identity (sum of combinatorial identity products 1 | sum of products 1 proof | sum of combinatorial identity products 2 | sum of products 2 proof)
PHP中register_globals参数设置
Reflection on some things
First!! Is lancet hungry? Official documents
TCP擁塞控制詳解 | 3. 設計空間
程序猿如何快速成长
Deep understanding of grouping sets statements in SQL
坚持输出需要不断学习
Three dimensional reconstruction of deep learning
Microservice - declarative interface call openfeign
“用Android复刻Apple产品UI”(2)——丝滑的AppStore卡片转场动画
Shell script import and export data
深度学习之三维重建
Slam learning notes - build a complete gazebo multi machine simulation slam from scratch (II)
NFT新的契机,多媒体NFT聚合平台OKALEIDO即将上线
MongoDB 的安装和基本操作
Microservice sentinel flow control degradation
Microservices - load balancing ribbon
关于网页中的文本选择以及统计选中文本长度