一:检查 Qt Creator 编译器版本

单击 Qt Creator 的 “帮助”–>“关于 Qt Creator”菜单,出现的对话框会显示 Qt Creator 的版本信息和使用的编译器信息。Qt5.9的 Qt Creator 是基于 MSVC2015 32bit 编译器编译的。

二:配置 MSVC2015 32bit 编译器

参见 Qt5 + msvc2015编译器 环境配置 (不安装VS)

三:自定义 Qt Designer 插件

1、设置插件项目名称和保存路径,本案例设置项目名称为 QwBatteryPlugin

2、选择项目编译器,保持和 Qt Creator 编译器版本一致,本案例就是 MSVC2015 32bit 编译器

3、设置自定义 QWidget 类的名称

本案例名称为 QwBattery
唯一需要注意的就是:

  • 在 Sources 选项卡中,设置 Icon:自定义 QWidget 显示图标
  • 在 Description 选项卡中设置分组(Group):分组(Group)是自定义组件在组件面板里的分组名称,这里设置为 My Widget

4、显示和设置插件、资源文件名称

一般用默认生成的即可。

5、完成设置,生成项目

6、组件类 QWidget 的定义

qwbattery.h

#ifndef QWBATTERY_H
#define QWBATTERY_H

#include <QtUiPlugin/QDesignerExportWidget>
#include <QWidget>
#include <QColor>
#include <QRect>
#include <QPainter>
/**
* @brief QDESIGNER_WIDGET_EXPORT 宏:用于将自定义组件类从插件导出给 Qt Designer 使用,
* 必须在类名称前使用此宏
*/
class QDESIGNER_WIDGET_EXPORT QwBattery : public QWidget
{
Q_OBJECT
//这是控件可编辑的属性:powerLevel对应类中一个私有属性 getPowerLevel、setPowerLevel、powerLevelChanged对应类中的方法
Q_PROPERTY(int powerLevel READ getPowerLevel WRITE setPowerLevel
NOTIFY powerLevelChanged DESIGNABLE true)

public:
QwBattery(QWidget *parent = 0);
void setPowerLevel(int pow);
int getPowerLevel();
void setWarnLevel(int warn);
int getWarnLevel();
//缺省大小
QSize sizeHint();
private:
QColor colorBack = Qt::white;
QColor colorBorder = Qt::black;
QColor colorPower = Qt::green;
QColor colorWarning = Qt::red;
int powerLevel = 60;
int warnLevel = 20;
protected:
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
signals:
void powerLevelChanged(int);
};

#endif

qwbattery.cpp

#include "qwbattery.h"

QwBattery::QwBattery(QWidget *parent) :
QWidget(parent)
{
}

void QwBattery::setPowerLevel(int pow)
{
powerLevel = pow;
emit powerLevelChanged(pow);
repaint();
}

int QwBattery::getPowerLevel()
{
return powerLevel;
}

void QwBattery::setWarnLevel(int warn)
{
warnLevel = warn;
repaint();
}

int QwBattery::getWarnLevel()
{
return warnLevel;
}

QSize QwBattery::sizeHint()
{
int height = this->height();
int width = height * 12 /5;
QSize size(width, height);
return size;
}

void QwBattery::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
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(colorBorder);
pen.setStyle(Qt::SolidLine);
pen.setCapStyle(Qt::FlatCap);
pen.setJoinStyle(Qt::BevelJoin);
painter.setPen(pen);
QBrush brush;
brush.setColor(colorBack);
brush.setStyle(Qt::SolidPattern);
painter.setBrush(brush);
rect.setRect(1, 1, 109, 48);
painter.drawRect(rect);
brush.setColor(colorBorder);
painter.setBrush(brush);
rect.setRect(110, 15, 10, 20);
painter.drawRect(rect);

if (powerLevel > warnLevel)
{
brush.setColor(colorPower);
pen.setColor(colorPower);
}
else
{
brush.setColor(colorWarning);
pen.setColor(colorWarning);
}
painter.setBrush(brush);
painter.setPen(pen);

if (powerLevel > 0)
{
rect.setRect(5, 5, powerLevel, 40);
painter.drawRect(rect);
}

QFontMetrics textSize(this->font());
QString powerStr = QString::asprintf("%d%%", powerLevel);
QRect textRect = textSize.boundingRect(powerStr);
painter.setFont(this->font());
pen.setColor(colorBorder);
painter.setPen(pen);
painter.drawText(55 - textRect.width() / 2, 23 + textRect.height() / 2, powerStr);
}

四、插件的编译与安装

插件在 Release 模式下编译,生成文件:qwbatteryplugin.dll 和 qwbatteryplugin.lib,插件在 Debug 模式下编译,生成文件:qwbatteryplugind.dll 和 qwbatteryplugind.lib,两个的区别就是 Debug 编译生成的文件名末尾多一个 “d” 字母。将 qwbatteryplugin.dll 和 qwbatteryplugind.dll 动态链接库文件复制到下面两个目录:

D:\Qt\Qt5.9.0\Tools\QtCreator\bin\plugins\designer
D:\Qt\Qt5.9.0\5.9\msvc2015\plugins\designer

重启 Qt Creator,使用 UI 设计器设计窗口时,在左侧的组件面板会看到增加一个 My Widget 分组,分组里面有一个组件 QwBattery:
二十一、Qt之自定义 Qt Designer 插件_编译器

五、使用自定义插件

1、新建一个项目 BatteryUser,设计界面如下:
二十一、Qt之自定义 Qt Designer 插件_#include_02
编辑 滑块控件和电池控件的槽函数:

void MyWidget::on_qwBattery_powerLevelChanged(int arg1)
{
QString str = QString::asprintf("当前电量:%d %%", arg1);
ui->labelInfo->setText(str);
}

void MyWidget::on_horizontalSlider_valueChanged(int value)
{
ui->battery->setPowerLevel(value);
}

2、在项目的源文件目录下创建一个 include 子目录,将 QwBattery 类定义的头文件 qwbattery.h 、插件的 debug 和 release 两种模式编译生成的库文件 qwbatteryplugind.lib 和 qwbatteryplugin.lib 复制到此目录下,项目在编译链接时需要此头文件和库文件。

3、导入库文件

方式一:引导方式
右击项目,在弹出的菜单中选择 “添加库…” ,选择库类型时,选择 外部库“External Library”;选择库文件位置时,就把 include 文件夹下的 qwbatteryplugin.lib 选中即可,会自动填充 “Include path”编辑框,选择 windows 平台,连接方式选择 Dynamic ,勾选下方 Add “d” suffix for debug version,表示在 debug 版本的库名称后面添加一个字母 “d”,以便编译器自动区分 release 和 debug 版本的库文件。

方式二:手动代码导入
修改项目文件 BatteryUser.pro,添加:

#设置添加的库文件,会判断当前项目时以 debug 还是 release 模式编译
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/include/ -lqwbatteryplugin
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/include/ -lqwbatteryplugind
#头文件目录
INCLUDEPATH += $$PWD/include
#项目依赖目录
DEPENDPATH += $$PWD/include

4、运行项目
此时可正常编译,但是无法正常运行,一旦运行,会直接崩溃,且无报错信息。
(1)第一步:编译
在 debug 和 release 两种模式下分别编译。
(2)第二步:复制插件的 dll 文件
将插件在 debug 和 release 两种模式下编译生成的 qwbatteryplugin.dll 和 qwbatteryplugind.dll 动态链接库文件分别复制到项目编译的两个文件夹下:

E:\Qt_Demo\build-BatteryUser-Desktop_Qt_5_9_0_MSVC2015_32bit-Debug\debug
E:\Qt_Demo\build-BatteryUser-Desktop_Qt_5_9_0_MSVC2015_32bit-Release\release

(3)第三步:运行
二十一、Qt之自定义 Qt Designer 插件_库文件_03

六、遇到的问题及解决办法

二十三、Qt5.9 + msvc2015编译器 环境配置 (不安装VS)

二十四、Qt lnk1158 无法运行rc.exe 解决方法

二十六、Qt之使用 MSVC编译器输出中文乱码的问题