网站首页 > 开源技术 正文
本文介绍为UI设计器设计自定义界面组件的Widget插件,直接安装到UI设计器的组件面板里,如同Qt自带的界面设计组件一样使用,在设计时就能看到组件的实际显示效果,只是编译和运行时需要使用到插件的动态链接库(Windows平台上)。
创建 Qt Designer Widget 插件项目
Qt提供两种设计插件的API,可以用于扩展Qt的功能。
高级(high-level) API用于设计插件以扩展Qt的功能,例如定制数据库驱动、图像格式、文本编码、定制样式等,Qt Creator里大量采用了插件,单击Qt Creator的主菜单栏的“Help” 一“About Plugins”菜单项,会显示Qt Creator里已经安装的各种插件。
低级(low-level) API用于创建插件以扩展自己编写应用程序的功能,最常见的就是将自定义Widget组件安装到UI设计器里,用于窗口界面设计。
本节创建一个与QBattery功能一样的类,但是采用创建Qt Designer 插件的方式来创建这个类,并将其安装到UI设计器的组件面板里。
要创建UI设计器插件类,单击Qt Creator的“File” 一 “New File or Project”菜单,在出现的对话框里选择“Other Project”分组的“Qt Custom Designer Widget”项目,会出现一个向导对话框。按照这个向导的操作逐步完成项目创建。
? 第1步:设置插件项目的名称和保存路径
本实例设置项目名称为QBatteryPlugin。
? 第2步:选择项目编译器
可以选择多个编译器,在编译时,再选择具体的编译器。但是实 际上只有MSVC2017 32bit编译器是能用的。
注意使用Qt创建的Widget插件,若要在Qt Creator的UI设计器里正常显示,编译插件的编译器版本必须和编译Qt Creator的版本一致。
Qt 5.14的 Qt Creator 是基于 MSVC2017 32bit 编译器编译的(单击 Qt Creator 的“Help”一“About Qt Creator”菜单,出现的对话框里会显示Qt Creator的版本信息和使用的编译器信息)。所以,为了在Qt Creator里设计窗体时能够正常显示插件,只能使用Qt 5.14 MSVC2017 32bit编译器。
? 第3步:设置自定义QWidget类的名称
只需在左侧的Widget classes列表里设置类名,右侧就会自动设置缺省的文件名,这里添加一个类QBattery。还可以选择一个图标文件作为自定义组件在UI设计器组件面板里的显示图标。
在Description页还可以设置Group、Tooltip和What’s this等信息,Group是自定义组件在组件面板里的分组名称,这里设置为“My Widget”。
? 第4步:显示和设置插件、资源文件名称
本实例缺省的插件名称是qbatteryplugin,资源文件名称为icons.qrc,一般用缺省的即可。
? 第5步:完成设置,生成项目
完成设置后生成的项目的文件组织结构如图所示,这些文件包括以下几个。
- QBatteryPlugin.pro是插件项目的项目文件,用于实现插件接口。
- qbatteryplugin.h 和 qbatteryplugin.cpp 是插件的头文件和实现文件。
- icons.qrc是插件项目的资源文件,存储了图标。
- qbattery.pri是包含在QBatteryPlugin.pro项目中的一个项目文件(图中选择“Include project”),用于管理自定义组件类。
- qbattery.h和qbattery.cpp是自定义类QBattery的头文件和实现文件。
插件项目各文件的功能实现
(1)QBatteryPlugin类
qbatteryplugin.h文件中的内容是对插件类QBatteryPlugin的定义,类定义完整代码如下(自动生成,无需修改):
#include <QDesignerCustomWidgetInterface>
class QBatteryPlugin : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface")
#endif // QT_VERSION >= 0x050000
public:
QBatteryPlugin(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;
};
QBatteryPlugin类实现了QDesignerCustomWidgetlnterface接口,这是专门为Qt Designer 设计自定义Widget组件的接口。
在这个类定义里,除了Q_OBJECT宏之外,还用Q_INTERFACES宏声明了实现的接口,用Q_PLUGIN_METADATA声明了元数据名称,这些都无需改动。
public部分的函数都是有关插件信息或功能的一些函数,通过其实现代码可以看出这些函数 的功能。
下面是qbatteryplugin.cpp文件里的实现代码(自动生成,无需修改)。
#include "qbattery.h"
#include "qbatteryplugin.h"
#include <QtPlugin>
QBatteryPlugin::QBatteryPlugin(QObject *parent)
: QObject(parent)
{
m_initialized = false;
}
void QBatteryPlugin::initialize(QDesignerFormEditorInterface * /* core */)
{
if (m_initialized)
return;
// Add extension registrations, etc. here
m_initialized = true;
}
bool QBatteryPlugin::isInitialized() const
{//是否初始化
return m_initialized;
}
QWidget *QBatteryPlugin::createWidget(QWidget *parent)
{//返回自定义Widget组件的实例
return new QBattery(parent);
}
QString QBatteryPlugin::name() const
{//自定义Widget组件类的名称
return QLatin1String("QBattery");
}
QString QBatteryPlugin::group() const
{//在组件面板中所属分组名称
return QLatin1String("My Widget");
}
QIcon QBatteryPlugin::icon() const
{//图标文件名
return QIcon(QLatin1String(":/battery.jpg"));
}
QString QBatteryPlugin::toolTip() const
{//toolTip 信息
return QLatin1String("Battery charger indicator");
}
QString QBatteryPlugin::whatsThis() const
{//whatsThis 信息
return QLatin1String("A battery charger indicator");
}
bool QBatteryPlugin::isContainer() const
{//是否作为容器,false表示该组件上不允许再放其他组件
return false;
}
QString QBatteryPlugin::domXml() const
{//XML文件描述信息
return QLatin1String("<widget class=\"QBattery\" name=\"qBattery\">\n</widget>\n");
}
QString QBatteryPlugin::includeFile() const
{//包含文件名
return QLatin1String("qbattery.h");
}
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2(qbatteryplugin, QBatteryPlugin)
#endif // QT_VERSION < 0x050000
这些函数的部分内容是根据创建插件向导里设置的内容自动生成的。createWidget()函数创建一个QBattery类的实例,在UI设计器里作为设计实例;name()函数返回组件的类名称;group()函数设置组件安装在面板里的分组名称;icon()设置组件的图标;isContainer()设置组件是否作为容器,false表示不作为容器,不能在这个组件上放置其他组件;domXml()函数用XML设置组件的一些属性,缺省的只设置了类名和实例名。
(2)QBatteryPlugin.pro 的内容
QBatteryPlugin.pro是插件项目的项目管理文件,其内容如下:
CONFIG += plugin debug_and_release
TARGET = $qtLibraryTarget(qbatteryplugin)
TEMPLATE = lib
HEADERS = qbatteryplugin.h
SOURCES = qbatteryplugin.cpp
RESOURCES = icons.qrc
LIBS += -L.
greaterThan(QT_MAJOR_VERSION, 4) {
QT += designer
} else {
CONFIG += designer
}
target.path = $[QT_INSTALL_PLUGINS]/designer
INSTALLS += target
include(qbattery.pri)
CONFIG是用于qkame编译设置的,这里配置为:
CONFIG += plugin debug_and_release
其中,plugin表示项目要作为插件,编译后只会产生lib和dll(或.so)文件,debug_and_release 表示项目可以用debug和release模式编译。
TEMPLATE定义项目的类型,这里设置为:
TEMPLATE = lib
这表示项目是一个库,一般的应用程序模板类型是app。
(3)内置项目 qbattery.pri
qbattery.pri是内置于QBatteryPlugin.pro中的项目,qwbattery.pri项目配置文件只有两行,
也就是这个内置项目中包含的头文件和源文件名称。
HEADERS += qbattery.h
SOURCES += qbattery.cpp
(4)组件类QBattery的定义
qbattery.h里的内容是对组件类QBattery的类定义,其功能与前一篇文章中的QBattery类完全一样。这两个类的名称之所以不同,是为了在编译两个实例时不产生冲突。
QBattery类的定义在声明类的时候需要加一个宏QDESIGNER_WIDGET_EXPORT,并且用 Q_PROPERTY宏定义了一个属性powerLevel。
QBattery类的完整定义如下:
#include <QWidget>
#include <QDesignerExportWidget>
class QDESIGNER_WIDGET_EXPORT QBattery : public QWidget
{
Q_OBJECT
//自定义属性
Q_PROPERTY(int powerLevel READ powerLevel WRITE setPowerLevel
NOTIFY powerLevelChanged DESIGNABLE true)
private:
QColor mColorBack=Qt::white; //背景颜色
QColor mColorBorder=Qt::black; //电池边框颜色
QColor mColorPower=Qt::green; // 电量柱颜色
QColor mColorWarning=Qt::red; // 电量短缺时的颜色
int mPowerLevel=60; // 电量0-100
int mWarnLevel=20; // 电量低警告阈值
protected:
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
public:
explicit QBattery(QWidget *parent = 0);
void setPowerLevel (int pow); //设置当前电量
int powerLevel();
void setWarnLevel(int warn);//设置电量低阈值
int warnLevel();
QSize sizeHint();//报告缺省大小
signals:
void powerLevelChanged(int );
public slots:
};
QDESIGNER_WIDGET_EXPORT宏用于将自定义组件类从插件导出给Qt Designer使用,必须在类名称前使用此宏。
Q_PROPERTY宏用于定义属性,这里定义了一个int类型的属性powerLevel。READ宏声明 了属性的读取函数是powerLevel(); WRITE宏声明了设置属性值的函数是setPowerLevel(); NOTIFY宏声明了其值变化时发射的信号是powerLevelChanged(); DESIGNABLE宏定义属性在 UI设计器里是否可见,缺省为true。
将从QWidget继承的子类QBattery作为插件安装到UI设计器的组件面板里,则在设计期间就可以从属性编辑器里看到这个powerLevel属性并进行设置。
QBattery类的实现代码与之前的实现代码完全相同,不再列出。
插件的编译与安装
使用MSVC2017 32bit编译器,将插件项目在release模式下编译,编译后会生成qbatteryplugin.dll 和 qbatteryplugin.lib 两个文件。
qbatteryplugin.dll是插件的动态链接库文件,需要将此文件复制到Qt Creator的插件目录和 Qt的插件目录下。例如,要是把Qt安装到了C:\Qt\Qt5.14.2目录下,就需要将qbatteryplugin.dll复制到如下两个目录下:
C:\Qt\Qt5.14.2\Tools\QtCreator\bin\plugins\designer
C:\Qt\Qt5.14.2\5.14.2\msvc2017\plugins\designer
重启Qt Creator,使用UI设计器设计窗口时,在左侧的组件面板里会看到增加了一个“My Widget” 分组,里面有一个组件QBattery。
编译和安装Widget插件必须注意以下事项。
- 要让插件在Qt creator的UI设计器里正常显示,编译插件项目的编译器必须与编译Qt Creator的编译器一致,否则,即使将编译后生成的DLL文件复制到Qt的目录下,Qt Creator 的UI设计器的组件面板里也不会出现自定义的组件。例如,Qt Creator 4.11.1是基于Qt 5.14.2和MSVC2017 32 bit编译器(单击 Qt Creator 的 “Help” 一 “About Qt Creator” 菜单项可以看到这些信息),那么编译插件就必须使用Qt 5.12.2 MSVC2017 32 bit编译器。
- 用debug和release模式编译的插件也分别只适用于debug和release模式编译的应用程序。在debug模式下编译的插件项目生成的Lib和DLL文件会在文件名最后自动增加一个字母“d”,例如,本项目在debug模式下编译生成的是 qbatteryplugind.dll和 qbatteryplugind.lib,这两个文件应用于使用此插件的应用程序的debug模式。
使用自定义插件
在Qt Creator的UI设计器的组件面板里能正常显示自定义的QBattery组件后,就可以在窗 体设计时使用QBattery组件了。
创建一个基于QWidget的实例应用程序BatteryUser。设计窗体时,从组件面板上拖放一个 QBattery到窗体上。在设计窗体时,就能直接看到QBattery绘制的电池图形,在属性编辑器里可以编辑QBattery组件的powerLevel属性,在其“Go to slot”对话框里会出现自定义的信号powerLevelChanged(int),可以为此信号设计槽函数。
下面的代码实现的是利用滑动条设置battery的当前电量值,在battery的powerLevelChanged()信号的槽函数里,将当前电量值显示在标签里,程序运行后就可以实现上一篇文章示例中相同的功能。
void Widget::on_horizontalSlider_valueChanged(int value)
{ // 拖动slider改变battery的电量
ui->battery->setPowerLevel(value);
}
void Widget::on_battery_powerLevelChanged(int arg1)
{ //电量值改变时,在标签中显示
QString str=QStringLiteral("当前电量:")+QString::asprintf ("%d %%", arg1);
ui->labInfo->setText(str);
}
注意项目BatteryUser只能用MSVC2017 32bit编译器进行编译,因为使用的Widget插件类QBattery是用MSVC2017 32bit 编译的。
要正常编译项目BatteryUser还需要做以下设置。
- 在项目的源文件目录下创建一个include子目录(名称随个人喜好设置),将QBattery类定义的头文件qbattery.h、插件的debug和release两种模式编译生成的库文件qbatteryplugin.lib 以及qbatteryplugind.lib复制到此目录下,项目在编译链接时需要使用此头文件和库文件。
- 在项目管理器中,选中BatteryUser项目节点并单击右键,在快捷菜单中单击“Add Library…”,在出现的向导对话框第一步中,选择库类型时,将外部库“External Library” 选中,因为本项目需要使用的是己经编译好的库文件。
- 在向导的第二步,单击“Library file”编辑框后面的按钮,选择include目录 下的库文件qwbatteryplugin.lib,会自动填充“Include path”编辑框。在平台选择中可以只选择一个 windows平台,连接方式选择Dynamic,下方的 Add “d” suffix for debug version 表示在debug版本的库名称后面添加一个字母“d”,以便编译器自动区分release和debug 版本的库文件。
完成“Add Library”对话框的设置后,QtCreator会自动修改项目文件BatteryUser.pro的内容,在其中添加了以下几行:
win32:CONFIG(release, debug|release): LIBS += -L$PWD/include/ -lqbatteryplugin
else:win32:CONFIG(debug, debug|release): LIBS += -L$PWD/include/ -lqbatteryplugind
INCLUDEPATH += $PWD/include
DEPENDPATH += $PWD/include
LIBS用于设置添加的库文件,会判断当前项目是以debug还是release模式编译,自动加入 qbatteryplugin.lib 或 qbatteryplugind.lib 库文件。
INCLUDEPATH和DEPENDPATH用于设置头文件目录和项目依赖项目录,都指向项目路径 下的include目录。
这样设置后,项目就可以在release或debug模式下编译了,同样只能使用MSVC2017 32bit编译器。 注意要运行应用程序,还需要将插件的DLL文件复制到编译后的release或debug版本的可执行文件目录下,在本例中就是qbatteryplugin.dll文件或qbatteryplugind.dll文件,因为应用程序运行需要相应的DLL文件。在应用程序发布时,也需要将DLL文件随同应用程序发布。
自定义Widget插件的功能使得我们可以扩展Qt Creator的组件种类,设计自己需要的组件。 也有许多第三方Widget插件可供直接使用,减少自己编程的工作量,例如QWT就是一套非常好的开源Widget插件。
猜你喜欢
- 2024-10-26 脚下每一步都是马赛克艺术(脚下走的每一步)
- 2024-10-26 Python GUI开发:PySide2使用入门(python gui程序)
- 2024-10-26 手把手教会 VS2022 设计 Winform 高DPI兼容程序 (net461 net6.0 双出)
- 2024-10-26 如何使用FastReport .NET 在 JetBrains Rider 中创建PDF报告?
- 2024-10-26 实战PyQt5: 002-安装和配置PyQt5开发环境
- 2024-10-26 触得到的时间--kickstarter上受到最多资助的项目
- 2024-10-26 今天再用10分钟,木辛老师带你一起走入界面布局管理的知识海洋吧
- 2024-10-26 51款工业风浴室超高逼格做法,真是太好用了
- 2024-10-26 由浅入深理解C#中的事件(c#事件的五要素)
- 2024-10-26 PYQT5学习(02):利用Qt Designer制作第一个窗口程序
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- jdk (81)
- putty (66)
- rufus (78)
- 内网穿透 (89)
- okhttp (70)
- powertoys (74)
- windowsterminal (81)
- netcat (65)
- ghostscript (65)
- veracrypt (65)
- asp.netcore (70)
- wrk (67)
- aspose.words (80)
- itk (80)
- ajaxfileupload.js (66)
- sqlhelper (67)
- express.js (67)
- phpmailer (67)
- xjar (70)
- redisclient (78)
- wakeonlan (66)
- tinygo (85)
- startbbs (72)
- webftp (82)
- vsvim (79)
本文暂时没有评论,来添加一个吧(●'◡'●)