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

目录

一、创建自定义控件插件

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_OBJECTQ_INTERFACES(QDesignerCustomWidgetCollectionInterface)
#if QT_VERSION >= 0x050000Q_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_OBJECTQ_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_OBJECTQ_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_OBJECTQ_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(); //加载dllif (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

转载请注明出处!!

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

QT自定义控件插件学习笔记相关推荐

  1. Qt 5.12学习笔记--QML性能策略

    Qt 5.12学习笔记--QML性能策略 1 简介 2 时间因素 2 性能分析 3 JavaScript 部分 4 绑定 5 类型转换 6 解析属性 6 属性绑定 7 序列提示(Sequence ti ...

  2. Gradle插件学习笔记(二)

    之前介绍了Gradle插件的开发,这次会对功能进行一部分拓展,建议没有读过第一篇文章的朋友,先看一下Gradle插件学习笔记(一) Extension 之前的文章提到过,如何编写一个插件,但是并不能通 ...

  3. Qt 快速入门学习笔记

    Qt 快速入门学习笔记 环境安装 环境配置以及安装 安装包下载地址 1.windows安装 msvc编译器模块需要安装Windows软件开发工具包. MinGW是Windows平台使用GNU工具导入库 ...

  4. QT 5.9学习笔记

    QT 5.9学习笔记 写在前面 S1:初识QT:QT简介 S2:QT在Windows和Linux平台下的安装 Qt调出模态与非模态对话框 写在前面 本文章为我在学习QT5.9时的记录文章,里面会涉及所 ...

  5. Unity Cinemachine插件学习笔记,实现单目标和多目标之间切换

    Unity Cinemachine插件学习笔记,实现单目标和多目标之间切换 *版本要求Unity2017.1及以上. 参考资料: [官方] Unity 2017.1正式版发布 Cinemachine插 ...

  6. Unity Cinemachine插件学习笔记

    以下都是转载内容,能够比较直观的学习一些基础内容.现在的Cinemachine更新了许多新的功能,但是Cinemachine插件都ExamplesScences,去看一下官方例子和文档来学习更佳 *版 ...

  7. Unity Cinemachine插件学习笔记,结合Timeline实现简单场景动画

    Unity Cinemachine插件学习笔记,结合Timeline实现简单场景动画 *版本要求Unity2017.1及以上. 参考资料: [官方] Unity 2017.1正式版发布 [Unity] ...

  8. Qt武林秘籍学习笔记摘要

    1 原文链接 Qt开发经验: 自己总结的这十多年来做Qt开发以来的经验,以及Qt相关武林秘籍电子书,会一直持续更新增加,欢迎各位留言增加内容或者提出建议,谢谢! (gitee.com) 编程语录: 自 ...

  9. JavaScript 封装插件学习笔记(一)

    此篇只是笔记,在借鉴.参考.模仿的过程,可能不完整,请多指教! 定义插件名称要注意命名冲突,防止全局污染. 1.第一种Javascript对象命名:(Javascript语言是"先解析,后运 ...

最新文章

  1. python脚本如何监听终止进程行为,如何通过脚本名获取pid
  2. ReactiveCocoa基础
  3. HDU1846 - Brave Game【巴什博弈】
  4. Java中String类型的概述
  5. 人人网,微博,QQ空间,朋友圈,常用API调用实现方法
  6. 19 矩阵——矩阵的相抵、相抵标准形、秩1矩阵、矩阵的满秩分解
  7. 数据持久化,序列化,反序列化,文件读写1
  8. php实现先序、中序、后序遍历二叉树
  9. 撰写商业计划书的一些误区和建议
  10. 超星尔雅python_超星尔雅Python金融数据分析答案公众号
  11. js 计算时间差 函数
  12. 腾讯云数据库CDB介绍及数据库与应用数据库分析
  13. 【C语言学习】sscanf的简单使用.
  14. 远程桌面连接只有2个会话活动
  15. 无线网卡无信号无服务器,无线网卡不能连接网络是什么原因?
  16. 删了手机里的一个html文件,手机操作篇:手机上怎么删除pdf其中一页
  17. 刷脸自助登记 访客管理不再潦草应对!
  18. 想通过手机刷视频赚钱?这篇文章你有必要了解一下
  19. 友盟推送 php,laravel5.4+umeng(友盟)集成app消息推送功能
  20. 求斐波那契数列c++实现

热门文章

  1. Debian AMD 64bit 折腾经历
  2. 互联网晚报 | 三星超过苹果成手机市场份额第一;特斯拉回应中国内地市场降价传闻;ChatGPT或会暴露企业机密信息...
  3. 【翻译】代码指针完整性——Code Pointer Integrity
  4. 【laravel-admin】权限管理与实现原理
  5. Android学习笔记(二)
  6. 计算机数控编程特点,什么是数控图像编程系统有哪些特点
  7. ORACLE sql 高级查询
  8. PostgreSQL服务端监听设置
  9. 谈谈String.intern方法
  10. 萌娃第一台电动车哪吒魔小童正式交付