QT自定义控件插件学习笔记

本文主要阐述的是自定义控件插件的创建与调用方法和注意事项点。

目录

一、创建自定义控件插件

1、Qt Designer专用接口

2、插件的自定义控件类接口

二、调用自定义控件插件

1、动态调用插件

2、静态调用插件

三、结语


一、创建自定义控件插件

1、Qt Designer专用接口

1.1、控件收集器接口

基类:QDesignerCustomWidgetCollectionInterface

用途:将所有自定义控件类装载到一个QList里面

#pragma once
#include <QtDesigner>
#include <qplugin.h>
​
class WidgetCollectionInterface : public QObject, public QDesignerCustomWidgetCollectionInterface
{
    Q_OBJECT
    Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)  
#if QT_VERSION >= 0x050000
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface")
#endif // QT_VERSION >= 0x050000
​
public:
    WidgetCollectionInterface(QObject* parent = 0);
​
    QList<QDesignerCustomWidgetInterface*> customWidgets() const override;
​
private:
    QList<QDesignerCustomWidgetInterface*> widgets;
};

关键点:

两个宏,声明唯一接口

Q_INTERFACES(QDesignerCustomWidgetCollectionInterface) 
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface")

构造函数中装载所有自定义控件类

WidgetCollectionInterface::WidgetCollectionInterface(QObject* parent)
    : QObject(parent)
{
    widgets.append(new MyProgressBar1Interface(this));
    //widgets.append(new CustomWidgetTwoInterface(this));
    //widgets.append(new CustomWidgetThreeInterface(this));
}

1.2、单个自定义控件接口

基类:QDesignerCustomWidgetInterface

用途:通过重写虚函数完成单个自定义控件信息的定义,使得Qt Designer可以通过dll动态调用方式加载到自定义控件的信息,

其信息包括控件图标、控件名字、控件头文件、控件所在组名、控件类名、Qt Designer拖拽自动生成的对象实例默认名称等

#pragma once
​
#include <QtUiPlugin/QDesignerCustomWidgetInterface>
#include <QtDesigner/QtDesigner>
class MyProgressBar1Interface : public QObject, public QDesignerCustomWidgetInterface
{
    Q_OBJECT
    Q_INTERFACES(QDesignerCustomWidgetInterface)
​
public:
    MyProgressBar1Interface(QObject *parent = Q_NULLPTR);
​
    bool isContainer() const;
    bool isInitialized() const;
    QIcon icon() const;
    QString domXml() const;
    QString group() const;
    QString includeFile() const;
    QString name() const;
    QString toolTip() const;
    QString whatsThis() const;
    QWidget *createWidget(QWidget *parent);
    void initialize(QDesignerFormEditorInterface *core);
​
private:
    bool initialized;
};

关键点:

基类QDesignerCustomWidgetInterface的虚函数重写

#include <QtUiPlugin/QDesignerCustomWidgetInterface>
#include <QtDesigner/QtDesigner>
class MyProgressBar1Interface : public QObject, public QDesignerCustomWidgetInterface
{
    Q_OBJECT
    Q_INTERFACES(QDesignerCustomWidgetInterface)
    ...    
    ...
    ...
}

2、插件的自定义控件类接口

2.1、自定义控件实现

控件继承的基类、控件属性、控件绘制、信号/槽、事件等常规的自定义控件实现,具体参考QPainter的使用

#pragma once
#include <QProgressBar>
#include <QFont>
#include <QColor>
#include <QBrush>
#include <QPen>
​
#include <QtDesigner/QtDesigner>
​
class QDESIGNER_WIDGET_EXPORT MyProgressBar1 :
    public QProgressBar
{
    Q_OBJECT
    Q_PROPERTY(QFont textFont READ getTextFont WRITE setTextFont)
    Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
    Q_PROPERTY(QPen circleLinePen READ getCircleLinePen WRITE setCircleLinePen)
    Q_PROPERTY(QBrush barBackgroundBrush READ getBarBackgroundBrush WRITE setBarBackgroundBrush)
    Q_PROPERTY(QBrush barForegroundBrush READ getBarForegroundBrush WRITE setBarForegroundBrush)
​
public:
    explicit MyProgressBar1(QWidget* parent = nullptr);
    virtual ~MyProgressBar1();
​
protected:
    virtual void paintEvent(QPaintEvent* event);
​
public:
    QFont getTextFont() const;
    void setTextFont(const QFont& font);
    QColor getTextColor() const;
    void setTextColor(const QColor& color);
    QPen getCircleLinePen() const;
    void setCircleLinePen(const QPen& pen);
    QBrush getBarBackgroundBrush() const;
    void setBarBackgroundBrush(const QBrush& brush);
    QBrush getBarForegroundBrush() const;
    void setBarForegroundBrush(const QBrush& brush);
​
private:
    QFont textFont; //字体格式
    QColor textColor; //字体颜色
    QPen circleLinePen; //圆轮廓画笔
    QBrush barBackgroundBrush; //进度条底色画刷
    QBrush barForegroundBrush; //进度条画刷
​
private:
    void InitUi();
    void TestPainter();
};
​

2.2、类接口导出

  • 使用QDESIGNER_WIDGET_EXPORT声明类,这个宏所在头文件是#include <QtDesigner/QtDesigner>
#include <QtDesigner/QtDesigner>
​
class QDESIGNER_WIDGET_EXPORT MyProgressBar1 : public QProgressBar
  • 预定义宏QDESIGNER_EXPORT_WIDGETS

    这个宏定义如下,所以一定要预定义宏QDESIGNER_EXPORT_WIDGETS,使其能导出接口,不然.dll是编译不过的。

#if defined(QDESIGNER_EXPORT_WIDGETS)
#  define QDESIGNER_WIDGET_EXPORT __declspec(dllexport)
#else
#  define QDESIGNER_WIDGET_EXPORT __declspec(dllimport)
#endif

二、调用自定义控件插件

1、动态调用插件

实现原理:主要通过.dll工程中的WidgetCollectionInterface、MyProgressBar1Interface等类来实现。先将所有自定义控件类装载到WidgetCollection,调用时再通过name()索引出自定义类,然后createWidget()。

用途:为了Qt Designer设计器能够一次性加载自定义控件插件中的所有控件,使用户可以通过拖拽等方式直接使用控件

特别注意:这种调用方式是不可以直接new自定义控件类的,只能通过下面的方式(LoadInterface、CreateCustomWidget)来调用自定义控件类的成员函数

bool CustomWidgetTestDemo::LoadInterface(QString pluginName)
{
    QFileInfo pluginFile( QString("%1/%2").arg(QCoreApplication::applicationDirPath()).arg(pluginName));
    QString pluginFilePath = pluginFile.absoluteFilePath();
    QPluginLoader load(pluginFilePath);
    QObject* obj = load.instance(); //加载dll
    if (obj != nullptr)
    {
        m_interface = qobject_cast<CustomWidgetCollectionInterface*>(obj);  //加载接口
        if (m_interface != nullptr)
        {
            return true;
        }
        else
        {
            QMessageBox::critical(this, "ERROR", QString::fromStdWString(L"CustomWidgetCollectionInterface加载失败!"));
        }
    }
    else
    {
        QMessageBox::critical(this, "ERROR", QString::fromStdWString(L"<%1>加载失败!").arg(pluginFilePath));
    }
    return false;
}
​
template<class T>
T* CustomWidgetTestDemo::CreateCustomWidget(QString name, QWidget* parent)
{
    QList<QDesignerCustomWidgetInterface*> widgets = m_interface->customWidgets();
    for each (QDesignerCustomWidgetInterface * var in widgets)
    {
        if (var->name() == name)
        {
            T* widget;
            widget = static_cast<T*>(var->createWidget(parent));
            if (widget != nullptr)
            {
                return widget;
            }
            break;
        }
    }
    QMessageBox::critical(this, "ERROR", QString::fromStdWString(L"自定义控件<%1>加载失败!").arg(name));
    return nullptr;
}
​
LoadInterface("QtCustomYihPlugin.dll");
MyProgressBar1* myProgressBar1 = CreateCustomWidget<MyProgressBar1>("MyProgressBar1", this);
myProgressBar1->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

2、静态调用插件

实现原理:主要通过.dll工程中的自定义控件类前面添加QDESIGNER_WIDGET_EXPORT来实现。实际上就是给.dll定义类接口

用途:为了能够实例化自定义控件类,即new自定义控件对象。.ui文件生成的源码,也是通过new来实例化自定义控件的,即类似下面的代码。

特别注意:与静态调用.dll方法一样,需要设置.lib依赖及其所在路径

MyProgressBar1* myProgressBar1_666;
myProgressBar1_666 = new MyProgressBar1(this);
myProgressBar1_666->setObjectName(QString::fromUtf8("myProgressBar1_1"));
myProgressBar1_666->setGeometry(QRect(320, 60, 271, 191));
myProgressBar1_666->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
m_Layout->addWidget(myProgressBar1_666);

三、结语

关于自定义控件的制作、控件插件的调用完整步骤等信息,可以参考以下资料:

互联网博客:<Qt编写自定义控件插件路过的坑及注意事项>

互联网博客:<Qt之自定义插件(for Qt Designer)>

书籍:<Qt Creator快速入门_第三版>

Demo源码(JaneYih PC):

解决方案名:CustomWidgetProject

创建插件工程名:QtCustomYihPlugin

调用插件工程名:CustomWidgetTestDemo

转载请注明出处!!

如有错误之处,请各路大神指点指点~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值