热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Qt:54自定义QtDesigner插件

一、创建QtDesignerWidget插件Qt提供两种设计插件的API,可以用于扩展Qt的功能高级API:用于设计插件以扩展Qt的功能࿰
一、创建Qt Designer Widget插件

Qt提供两种设计插件的API,可以用于扩展Qt的功能

  • 高级API:用于设计插件以扩展Qt的功能,例如定制数据库驱动、图像格式、文本编码、定制样式等。Qt有大量采用了插件,单击Qt Creator的主菜单栏的“Help” ==>“About Plugins”菜单项,会显示Qt Creator里已经安装的各种插件

  • 低级API:用于创建插件以扩展自己编写应用程序的功能,最常见的就是将自定义Widget组件安装到UI设计器里,用于窗口界面设计

二、UI设计器插件的设计

第一步

  • 单击Qt Creator的“File”→“New File or Project”菜单,然后选择“Qt Custom Designer Widget”


第二步

  • 设置项目名称为“QwBatteryPlugin”


第三步

  • 选择编译器的版本
  • 使用Qt创建的Widget插件,若要在Qt Creator的UI设计器里正常显示,编译插件的编译器版本必须和编译Qt Creator的版本一致
  • 可以通过点击Qt Creator的“Help”→“About Qt Creator”菜单查看Qt Creator的版本

  • 由于版本为msvc 2015 32bit,所以下面也要选择MSVC2015 32bit


第四步

  • 设置自定义QWidget类的名称,此处设为“QwBattery”。在Icon file处选择一个图片,作为自定义组件在UI设计器组件面板里的显示图标

  • 在Description页还可以设置Group、Tooltip、What's this等信息,Group是自定义组件在UI面板里的分组名称,此处我们设置为“My Widget”


第五步

  • 此处设置插件、资源文件名称。我们采用默认值


第六步

之后生成这些文件

  • QwBatteryPlugin.pro:插件项目的项目文件,用于实现插件接口
  • qwbatteryplugin.h和qwbatteryplugin.cpp:分别是插件的头文件和实现文件
  • icons.qrc:插件项目的资源文件,存储了图标
  • qwbattery.pri:是包含在QwBatteryPlugin.pro项目中的一个项目文件,是第四步图中勾选“Include project”产生的,用于管理自定义组件类
  • qwbattery.h和qwbattery.cpp:分别是自定义类QwBattery的头文件和实现文件


第七步

  • qwbatteryplugin.h的内容如下,这些成员都是系统自定义的(是对插件类QwBatteryPlugin的定义)
  • QwBatteryPlugin类实现了QDesignerCustomWidgetInterface结构,这是专门为Qt Designer设计自定义Widget组件的接口
  • Q_INTERFACES宏声明了实现的接口
  • Q_PLUGIN_METADATA声明了元数据名称
  • public部分:有关插件信息或功能的一些函数

#include class QwBatteryPlugin : public QObject, public QDesignerCustomWidgetInterface
{Q_OBJECTQ_INTERFACES(QDesignerCustomWidgetInterface)
#if QT_VERSION >= 0x050000Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface")
#endif // QT_VERSION >= 0x050000public:QwBatteryPlugin(QObject *parent = 0);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 m_initialized;
}


第八步

  • qwbatteryplugin.cpp的内容如下,这些成员也都是系统自定义的

QwBatteryPlugin::QwBatteryPlugin(QObject *parent): QObject(parent)
{m_initialized = false;
}void QwBatteryPlugin::initialize(QDesignerFormEditorInterface * /* core */)
{if (m_initialized)return;// Add extension registrations, etc. herem_initialized = true;
}bool QwBatteryPlugin::isInitialized() const
{ //是否初始化return m_initialized;
}QWidget *QwBatteryPlugin::createWidget(QWidget *parent)
{ //创建并返回自定义Widget组件的实例return new QwBattery(parent);
}QString QwBatteryPlugin::name() const
{ //返回自定义Widget组件类的名称return QLatin1String("QwBattery");
}QString QwBatteryPlugin::group() const
{ //返回在组件面板中所属分组名称return QLatin1String("My Widget");
}QIcon QwBatteryPlugin::icon() const
{ //返回图标文件名return QIcon(QLatin1String(":/battery.ico"));
}QString QwBatteryPlugin::toolTip() const
{ //toolTip信息return QLatin1String("Battery charger indicator");
}QString QwBatteryPlugin::whatsThis() const
{ //what's this的信息return QLatin1String("A battery charger indicator");
}bool QwBatteryPlugin::isContainer() const
{ //是否作为容器,false表示该组件上不允许再放其他组件return false;
}QString QwBatteryPlugin::domXml() const
{ //XML文件描述信息return QLatin1String("\n\n");
}QString QwBatteryPlugin::includeFile() const
{ //包含文件名return QLatin1String("qwbattery.h");
}
#if QT_VERSION <0x050000
Q_EXPORT_PLUGIN2(qwbatteryplugin, QwBatteryPlugin)
#endif // QT_VERSION <0x050000


第九步

  • QwBatteryPlugin.pro的内容如下

CONFIG &#43;&#61; plugin debug_and_release #CONFIG采用qkame编译
#plugin表示项目要作为插件&#xff0c;编译后只会产生.lib和.dll&#xff08;或.so&#xff09;文件
#debug_and_release表示项目可以用debug和release模式编译TARGET &#61; $$qtLibraryTarget(qwbatteryplugin)
TEMPLATE &#61; lib #TEMPLATE定义项目的类型&#xff0c;这里使用lib表示项目是一个库&#xff0c;一般的应用程序该处填写的是appHEADERS &#61; qwbatteryplugin.h
SOURCES &#61; qwbatteryplugin.cpp
RESOURCES &#61; icons.qrc
LIBS &#43;&#61; -L. greaterThan(QT_MAJOR_VERSION, 4) {QT &#43;&#61; designer
} else {CONFIG &#43;&#61; designer
}target.path &#61; $$[QT_INSTALL_PLUGINS]/designer
INSTALLS &#43;&#61; targetinclude(qwbattery.pri)


第十步

  • qwbttery.h的内容如下&#xff0c;此处不是系统自定义的&#xff0c;需要我们自己手动给出&#xff08;也是对组件类QwBattery的类定义&#xff0c;之所以与qwbatteryplugin.h的类名不同&#xff0c;是为了编译时不产生冲突&#xff09;
  • 将从WEidget继承的子类QwBattery作为插件安装到UI设计器的组件面板里&#xff0c;则在设计期间就可以从属性编辑器里看到这个powerLevel属性并进行设置
  • QDESIGNER_WIDGET_EXPORT宏&#xff1a;用于将自定义组件类从插件导出给Qt Designer使用&#xff0c;必须在QwBattery类名前使用
  • Q_PROPERTY宏&#xff1a;用于定义属性。此处定义了一个int类型的属性powerLevel&#xff1b;READ宏声明了属性的读取函数时powerLevel()&#xff1b;WRITE宏生命了设置属性值的函数时setPowerLevel()&#xff1b;NOTIFY宏生命了其值变化时发射的信号是powerLevelChanged()&#xff1b;DESIGNABLE宏定义属性在UI设计器里是否可见&#xff0c;缺省为true
  • powerLevelChanged(int)信号函数&#xff1a;没有实现&#xff0c;而是当自定义的插件被使用时&#xff0c;使用者调用插件的go to slot&#xff0c;选择powerLevelChanged(int)函数时&#xff0c;在里面实现相应的功能。并且这个信号在调用setPowerLevel函数中emit触发才执行

#include
#include
#include
#include
class QDESIGNER_WIDGET_EXPORT QwBattery : public QWidget
{Q_OBJECTQ_PROPERTY(int powerLevel READ powerLevel WRITE setPowerLevel NOTIFY powerLevelChanged DESIGNABLE true)
public:QwBattery(QWidget *parent &#61; 0);
private:QColor mColorBack&#61;Qt::white; //背景色QColor mColorBorder&#61;Qt::black;//电池边框颜色QColor mColorPower&#61;Qt::green; //电量柱颜色QColor mColorWarning&#61;Qt::red; //电量短缺时的颜色int mPowerLevel&#61;60; //当前电量&#xff08;0-100&#xff09;int mWarnLevel&#61;20; //电量低警示阀值
protected:void paintEvent(QPaintEvent *event)Q_DECL_OVERRIDE; //绘图
public:void setPowerLevel(int pow); //设置当前电量int powerLevel(); //得到当前电量void setWarnLevel(int warn); //设置电量低阀值int warnLevel(); //得到电量低阀值QSize sizeHint(); //返回组件的缺省大小
signals://当电量值改变时发射此信号void powerLevelChanged(int);
};


第十一步

  • qwbttery.cpp的相关函数定义

void QwBattery::paintEvent(QPaintEvent *event)
{Q_UNUSED(event);QPainter painter(this);//设置QPainter的绘图区QRect rect(0,0,width(),height());painter.setViewport(rect);painter.setWindow(0,0,120,50);painter.setRenderHint(QPainter::Antialiasing);painter.setRenderHint(QPainter::TextAntialiasing);//设置画笔QPen pen;pen.setWidth(2);pen.setColor(mColorBorder);pen.setStyle(Qt::SolidLine);pen.setCapStyle(Qt::FlatCap);pen.setJoinStyle(Qt::BevelJoin);//设置画刷QBrush brush;brush.setColor(mColorBack);brush.setStyle(Qt::SolidPattern);painter.setPen(pen);painter.setBrush(brush);//改变rect的区域&#xff0c;绘制电池边框rect.setRect(1,1,109,48);painter.drawRect(rect);//改变画刷颜色&#xff0c;改变rect的区域&#xff0c;绘制电池的正极头brush.setColor(mColorBorder);painter.setBrush(brush);rect.setRect(110,15,10,20);painter.drawRect(rect);//画电池柱if(mPowerLevel>mWarnLevel) //正常颜色电量柱{brush.setColor(mColorPower);pen.setColor(mColorPower);}else//电量低时电量柱{brush.setColor(mColorWarning);pen.setColor(mColorWarning);}painter.setBrush(brush);painter.setPen(pen);if(mPowerLevel>0)//如果当前有电量&#xff0c;绘制电量柱{rect.setRect(5,5,mPowerLevel,40);painter.drawRect(rect);}//绘制电量百分比文字QFontMetrics textSize(this->font());QString powerStr&#61;QString::asprintf("%d%%",mPowerLevel);QRect textRect&#61;textSize.boundingRect(powerStr); //得到字符串的rectpainter.setFont(this->font());pen.setColor(mColorBorder);painter.setPen(pen);painter.drawText(55-textRect.width()/2,23&#43;textRect.height()/2,powerStr);;}

//设置当前电量
void QwBattery::setPowerLevel(int pow)
{mPowerLevel&#61;pow;emit powerLevelChanged(pow);repaint();
}//得到当前电量
int QwBattery::powerLevel()
{return mPowerLevel;
}//设置电量低阀值
void QwBattery::setWarnLevel(int warn)
{mWarnLevel&#61;warn;repaint();
}//得到电量低阀值
int QwBattery::warnLevel()
{return mWarnLevel;
}//返回组件尺寸大小
QSize QwBattery::sizeHint()
{int H&#61;this->height();int W&#61;H*12/5;QSize size(W,H);return size;
}


三、插件的编译

二中的代码设计好之后&#xff0c;就可以开始编译了

第一步&#xff1a;

  • 用debug和release模式编译的插件分别只适用于debug和release模式编译的应用程序。在debug模式下编译的插件项目生成的lib和dll文件会在文件名最后自动增加一个字母d
  • 此处我们将项目在release模式下、debug模式下都编译一遍

  • release编译后会生成qwbatteryplugin.dll和qwbatteryplugin.lib两个文件&#xff0c;debug编译后会生成qwbatteryplugind.dll和qwbatteryplugind.lib两个文件。这两个文件是在bulid的文件夹下&#xff0c;而不是在当前项目的文件夹下


第二步&#xff1a;

  • qwbatteryplugin.dll是插件的动态链接库文件&#xff0c;需要将此文件复制到Qt Creator的插件目录和Qt的插件目录下
  • 例如Qt Creator安装到D:\Qt\Qt5.9.1目录下&#xff0c;就需要将qwbatteryplugin.dll复制到如下的两个目录下


第三步&#xff1a;

  • 重启Qt Creator&#xff0c;随意打开一个项目文件&#xff0c;就可以看到在UI界面生成了我们自定义的组件&#xff0c;并且可以使用


四、使用自定义插件

第一步&#xff1a;

  • 创建一个基于QWidget的实例应用程序BatteryUser
  • 然后从UI中拖动我们自定义的组件和一个滚动条和Label标签到界面中


第二步&#xff1a;

想要使用这个插件&#xff0c;还需要做一些设置

  • ①在项目的源文件目录下创建一个include目录&#xff08;这个目录的名称随意设置&#xff09;

  • ②将插件的QwBattery类定义的头文件qwbattery.h、插件的debug和release两种模式编译生成的库文件qwbatteryplugin.lib、qwbatteryplugind.lib复制到include目录下&#xff0c;项目在编译链接时需要使用到此头文件和库文件

  • ③右击“BatteryUser”项目&#xff0c;选择“Add Library...”&#xff0c;在出现的向导对话框第一步中&#xff0c;选择库类型时&#xff0c;将外部库“External Libary”选中&#xff0c;因为本项目需要使用的是已经编译好的库文件

  • ④在Library file中选择我们刚才在项目的include目录下复制的qwbatteryplugin.lib文件&#xff0c;选择之后会自动填充Include path&#xff0c;平台只选择Windows&#xff1b;连接方式选择Dynamic&#xff1b;下方的Add “d”......表示在debug版本的库名称后面添加一个字符“d”&#xff0c;以便编译器自动区分release和debug版本的库文件

  • ⑤之后会在项目文件中自动添加这几行内容&#xff08;LIBS用于设置添加的库文件&#xff0c;会判断当前项目是以debug还是release模式编译&#xff0c;自动加入qwbatteryplugin.lib或qwbatteryplugind.lib库文件&#xff1b;INCLUDEPATH和DEPENDPATH用于设置头文件目录和项目依赖项目录&#xff0c;都指向项目路径下的include目录&#xff09;

这样设置之后&#xff0c;项目就可以在release或者debug模式下编译了&#xff0c;只能使用MSVC2015 32bit编译器&#xff08;因为插件使用32bit编译器生成的&#xff09;


第三步&#xff1a;

  • 要运行应用程序&#xff0c;还需要将插件的在release和debug版本下编译产生的.dll文件复制到项目的release或debug版本的可执行文件(.exe)目录下&#xff0c;因为应用程序运行需要相应的dll文件&#xff0c;在应用程序发布时&#xff0c;也需要将dll文件随同应用程序发布


第四步&#xff1a;

  • 项目在编译的时候&#xff0c;我们插件的头文件会显示找不到#include 头文件&#xff0c;也就找不到QDESIGNER_WIDGET_EXPORT宏了&#xff0c;因此将这两个删除或注释


第五步&#xff1a;

  • 实现滚动条的valueChanged信号&#xff0c;当滚动条滚动时&#xff0c;调用qwbattery插件的setPowerLevel函数&#xff08;该函数会重绘qwbattery插件&#xff0c;并且emit发射powerLevelChanged信号&#xff09;

void Widget::on_horizontalSlider_valueChanged(int value)
{ //拖动slider改变battery的电量值ui->qwBattery->setPowerLevel(value);
}


第五步&#xff1a;

  • 实现qwbattery插件的powerLevelChanged()信号函数

void Widget::on_qwBattery_powerLevelChanged(int arg1)
{ //电量改变时&#xff0c;在label标签中显示QString str&#61;QStringLiteral("当前电量&#xff1a;")&#43;QString::asprintf("%d %%",arg1);ui->label->setText(str);
}


第六步

  • 在32位编译器的debug模式下编译演示一下&#xff0c;可以看到功能实现&#xff08;其他版本的编译器编译会报错&#xff0c;因为插件是在MSVC2015 32bit版本下编译生成的&#xff09;


五、自定义插件的第2方法
  • 将在UI界面设计好的窗口部件&#xff0c;直接拖拽到“组件箱”&#xff0c;会自动生成“Scratchpad”栏&#xff0c;自定义的组件会放置在这个栏下&#xff0c; 下次直接使用即可

  • 例如将一个TextEdit的组件拖拽到“组件箱”&#xff0c;下次可以直接使用


推荐阅读
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文由编程笔记#小编整理,主要介绍了关于数论相关的知识,包括数论的算法和百度百科的链接。文章还介绍了欧几里得算法、辗转相除法、gcd、lcm和扩展欧几里得算法的使用方法。此外,文章还提到了数论在求解不定方程、模线性方程和乘法逆元方面的应用。摘要长度:184字。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • 在2022年,随着信息化时代的发展,手机市场上出现了越来越多的机型选择。如何挑选一部适合自己的手机成为了许多人的困扰。本文提供了一些配置及性价比较高的手机推荐,并总结了选择手机时需要考虑的因素,如性能、屏幕素质、拍照水平、充电续航、颜值质感等。不同人的需求不同,因此在预算范围内找到适合自己的手机才是最重要的。通过本文的指南和技巧,希望能够帮助读者节省选购手机的时间。 ... [详细]
  • 本文讨论了微软的STL容器类是否线程安全。根据MSDN的回答,STL容器类包括vector、deque、list、queue、stack、priority_queue、valarray、map、hash_map、multimap、hash_multimap、set、hash_set、multiset、hash_multiset、basic_string和bitset。对于单个对象来说,多个线程同时读取是安全的。但如果一个线程正在写入一个对象,那么所有的读写操作都需要进行同步。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
author-avatar
董高峯_535
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有