Qt自定义 Qt Designer 插件

创建 Qt Designer 插件项目

Qt 提供两种设计插件的 API,可以用于扩展 Qt 的功能。高级 API 用于设计插件以扩展 Qt 的功能,例如定制数据库驱动、图像格式、文本编码、定制样式等。Qt Designer 里大量采用了插件,点击 Qt Creator 的“Help”->“About Plugins”菜单项,会显示 Qt Creator 里已经安装的各种插件。
低级 API 用于创建插件以扩展自己编写应用程序的功能,最常见的就是将自定义 Widget 组件安装到 UI 设计器里,用于窗口界面设计。本篇文章就将上一篇中的窗口电池组件编写成 UI 组件安装到 UI 设计器中。

查看 Qt Creator 所使用的编译器

想要编译出 UI 设计器中可以使用的插件,就需要知道编译 Qt Creator 的编译器,查看方式如下:

image.png

image.png

从“关于”中可以看出,我这个版本的 Qt Creator 是使用 MSVC2019 编译器编译出来的,所以我们在创建插件项目的使用需要使用 MSVC2019 编译器。

创建插件项目

  • 第一步是设置项目名称和保存路径,这里我取名叫 QwBatteryPlugin
  • 第二步是选择项目编译器,可以选择多个编译器,在编译时,再选择具体的编译器。但是实际上我们只能选择 MSVC2019 才有用。
  • 第三步是自定义 QWidget 类的名称,需要在左侧的 WIdget classes 列表里设置类名,右侧就会自动补全文件名,这里我添加一个 QwBattery 类。还可以选择一个图标作为自定义组件在 UI 设计器组件面板里的显示图形。

参考步骤如下:

image.png

image.png

image.png

image.png

image.png

插件项目各文件的功能实现

QwBatteryPlugin 类

qwbatteryplugin.h 文件中的内容是对插件类 QwBatteryPlugin 的定义,类定义完成代码如下:

#ifndef QWBATTERYPLUGIN_H
#define QWBATTERYPLUGIN_H

#include <QDesignerCustomWidgetInterface>

class QwBatteryPlugin : public QObject, public QDesignerCustomWidgetInterface
{
    Q_OBJECT
    Q_INTERFACES(QDesignerCustomWidgetInterface)
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface")

public:
    explicit QwBatteryPlugin(QObject *parent = nullptr);

    bool isContainer() const override;
    bool isInitialized() const override;
    QIcon icon() const override;
    QString domXml() const override;
    QString group() const override;
    QString includeFile() const override;
    QString name() const override;
    QString toolTip() const override;
    QString whatsThis() const override;
    QWidget *createWidget(QWidget *parent) override;
    void initialize(QDesignerFormEditorInterface *core) override;

private:
    bool m_initialized = false;
};

#endif // QWBATTERYPLUGIN_H

QwBatteryPlugin 类实现了 QDesignerCustomWidgetInterface 接口,这是专门为 Qt Designer 设计自定义 WIdget 组件的接口。在这里类的定义里,除了 Q_OBJECT 宏以外,还用了 Q_INTERFACES 声明了实现的接口,用 Q_PLUGIN_METADATA 声明了元数据名称,这些都无需改动。
public 部分的函数都是观察插件信息或功能的一些函数,通过其实现代码可以看出这些函数的功能。下面是 qwbatteryplugin.cpp 文件里实现的代码:

#include "qwbatteryplugin.h"
#include "qwbattery.h"

#include <QtPlugin>

QwBatteryPlugin::QwBatteryPlugin(QObject *parent)
    : QObject(parent)
{}

void QwBatteryPlugin::initialize(QDesignerFormEditorInterface * /* core */)
{
    if (m_initialized)
        return;

    // Add extension registrations, etc. here

    m_initialized = true;
}

bool QwBatteryPlugin::isInitialized() const
{
    return m_initialized;
}

QWidget *QwBatteryPlugin::createWidget(QWidget *parent)
{
    return new QwBattery(parent);
}

QString QwBatteryPlugin::name() const
{
    return QLatin1String("QwBattery");
}

QString QwBatteryPlugin::group() const
{
    return QLatin1String("");
}

QIcon QwBatteryPlugin::icon() const
{
    return QIcon(QLatin1String(":/batteryicon.ico"));
}

QString QwBatteryPlugin::toolTip() const
{
    return QLatin1String("");
}

QString QwBatteryPlugin::whatsThis() const
{
    return QLatin1String("");
}

bool QwBatteryPlugin::isContainer() const
{
    return false;
}

QString QwBatteryPlugin::domXml() const
{
    return QLatin1String(R"(<widget class="QwBattery" name="qwBattery">
</widget>)");
}

QString QwBatteryPlugin::includeFile() const
{
    return QLatin1String("qwbattery.h");
}

这些函数的部分内容是根据创建插件向导里设置的内容自动生成的。createWidget() 函数创建一个 QwBattery 类的实例,在 UI 设计器里作为设计实例;name() 函数返回组件的类名称;group() 函数设置组件安装在面板里的分组名称;icon() 设置组件的图标;isContaoner() 设置组件是否作为容器,false 表示不作为容器,不能在这个组件上放置其他组件;domXml() 函数用 XML 设置组件的一些属性,缺省的只设置类名和实例名。

QWBatteryPlugin.pro 的内容

QwBatteryPlugon.pro 是插件项目的项目管理文件,内容如下:

# 表示项目作为插件,编译后只有lib和dll(或so)
CONFIG      += plugin debug_and_release
TARGET      = $$qtLibraryTarget(qwbatteryplugin)
# 项目是一个库,一般的应用程序模版类型是app
TEMPLATE    = lib

HEADERS     = qwbatteryplugin.h
SOURCES     = qwbatteryplugin.cpp
RESOURCES   = icons.qrc
LIBS        += -L. 

QT += designer

target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS    += target

include(qwbattery.pri)

内置项目 qwbattery.pri

HEADERS += qwbattery.h
SOURCES += qwbattery.cpp

组件类 QWBattery 定义

QWBattery 类的定义与上一篇文章中的定义基本一样,只是在声明类的时候需要添加一个宏 QDESIGNER_WIDGET_EXPORT,并且用 Q_PROPERTY 宏定义了一个属性 powerLevel。完整定义如下:

#ifndef QWBATTERY_H
#define QWBATTERY_H

#include <QDesignerExportWidget>
#include <QWidget>
#include <QPaintEvent>

class QDESIGNER_WIDGET_EXPORT QwBattery : public QWidget
{
    Q_OBJECT
    Q_PROPERTY(int powerLevel READ powerLevel WRITE setPowerLevel NOTIFY powerLevelChanged DESIGNABLE true) // designable
public:
    explicit QwBattery(QWidget *parent = nullptr);
    void setPowerLevel(int pow);
    int powerLevel();
    void setWarnLevel(int warn);
    int warnLevel();
    QSize sizeHint();

signals:
    void powerLevelChanged(int);

private:
    QColor mColorBack = Qt::white;
    QColor mColorBorder = Qt::black;
    QColor mColorPower = Qt::green;
    QColor mColorWarning = Qt::red;
    int mPowerLevel = 60;
    int mWarnLevel = 20;

protected:
    void paintEvent(QPaintEvent* event) override;

};

#endif // QWBATTERY_H
  • QDESIGNER_WIDGET_EXPORT 宏表示将自定义的组件类从插件导出给 Qt Designer 使用,必须在类名钱使用此宏。
  • Q_PROPERTY 宏定义属性,这里定义了一个 int 类型的属性 powerLevel。READ 宏声明了属性的读取函数时 powerLevel();WRITE 宏声明了设置属性值的函数是 setPowerLevel();NOTIFY 宏声明了其值变化时发射的信号是 powerLevelChanged();DWSIGNABLE 宏定义属性在 UI 设计器里是否可见,缺省为 true。

插件的编译和安装

image.png

在写完代码后,分别在 debug 和 release 模式下进行构建(注意不是运行),然后在对应的 debug 和 release 目录就会生成 dll 和 lib 文件。分别将 debug 和 release 产生的 dll 文件复制到以下两个目录:

C:\Qt6\6.7.3\msvc2019_64\plugins\designer
C:\Qt6\Tools\QtCreator\bin\plugins\designer

重启 Qt Creator,使用 UI 设计器设计窗口时,在左侧的组件面板里就会看到我们刚刚自定义的插件:

image.png

使用自定义插件

在项目源文件目录下创建一个 include 文件夹,将用到的插件的 头文件lib 文件都复制进去,然后在 Qt Creator 中添加外部库。

image.png

添加后,项目配置文件会添加如下的依赖:

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

使用 MSVC 编译器输出中文的问题

在 Qt Creator 中使用 MSVC 编译器编译项目时,若处理不当容易出现中文字符串乱码的问题。这是由于 Qt Creator 保存的文件使用的是 UTF-8 编码,MSVC 编译器虽然可以正常编译 BOM 的 UTF-8 编码的源文件,但是生成的可执行文件的编码是 Windows 本地字符集,比如 GB 2312。也就是在可执行文件中,字符串“当前电量”是以 GB2312 编码的,而可执行程序执行这条语句时,是对这个字符串以 UTF-8 解码的,这样就出现了乱码。
解决这个问题的办法有两种,一种是使用 QStringLiteral() 宏封装字符串,另一种方法是强制 MSVC 编译器生成的可执行文件使用 UTF-8 编码。QStringLiteral(str) 宏在编译时将一个字符串 str 生成字符串数据,并且存储在编译后文件的只读数据段中,程序运行时使用到此字符串时,只需要读出此字符串数据即可。所以,我们可以这么写:

QString str = QStringLiteral("当前电量:") + QString::asprintf("%d%%", arg1);

程序中需要使用 QStringLiteral() 宏对每个中文字符串进行封装,并且不能再使用 tr() 函数用于翻译字符串;强制 MSVC 编译器采用 UTF-8 编码生成可执行文件,需要在每个使用到中文字符串的头文件和源文件的前部加上如下语句:

#if __MSC_VER >= 160
#pragma execution_character_set("utf-8")
#endif

参考资料:https://github.com/0voice

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/926982.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

周鸿祎再次“创业”,盯上百度

周鸿祎特地拍了部短剧来推广的新产品&#xff0c;终于上线了。 11月27日晚间&#xff0c;360正式发布多模态内容创作引擎“纳米搜索”。 作为当前AI应用最红的赛道之一&#xff0c;AI搜索已经有腾讯、秘塔、商汤、抖音等公司入局。传统搜索老大百度也在发力。竞争不妨碍有搜索…

003 MATLAB基础计算

01 方程组的求解 多项式及其运算 多项式在MATLAB中以向量形式存储。 即n次多项式用一个长度为n1的系数向量来表示&#xff0c;且按降幂&#xff0c;缺少的幂次对应的向量元素为0。 多项式的运算主要包括多项式的四则运算、求导、求值和求根运算 多项式的四则运算&#xff1a…

金蝶云苍穹:个人上传授权文件

金蝶云苍穹开发者门户--下载文件地址。

解决windows下php8.x及以上版本,在Apache2.4中无法加载CURL扩展的问题

本文已首发于&#xff1a;秋码记录 若你也想搭建一个个人博客&#xff0c;可参考&#xff1a;国内 gitee.com Pages 下线了&#xff0c;致使众多站长纷纷改用 github、gitlab Pages 托管平台 在日新月异的信息化下&#xff0c;软件也在跟随着互联网的脚步&#xff0c;逐步推进…

数据库管理-第267期 23ai:Oracle Data Redaction演示(20241128)

数据库管理267期 2024-11-286 数据库管理-第267期 23ai&#xff1a;Oracle Data Redaction演示&#xff08;20241128&#xff09;1 示例表及数据2 创建编校策略2.1 名字全编校2.2 电话部分编校 3 DML演示3.1 场景13.2 场景2 总结 数据库管理-第267期 23ai&#xff1a;Oracle Da…

根据电池容量及功耗估算充电及放电时间

根据电池容量和功耗估算充电和放电时间的方法可以通过以下简单的公式进行&#xff1a; 1. 估算放电时间 放电时间是指电池在一定功耗下&#xff0c;能够持续供应电力的时间。可以使用以下公式&#xff1a; 解释&#xff1a; 电池容量&#xff1a;电池的容量一般以毫安时&…

【Maven】继承和聚合

5. Maven的继承和聚合 5.1 什么是继承 Maven 的依赖传递机制可以一定程度上简化 POM 的配置&#xff0c;但这仅限于存在依赖关系的项目或模块中。当一个项目的多个模块都依赖于相同 jar 包的相同版本&#xff0c;且这些模块之间不存在依赖关系&#xff0c;这就导致同一个依赖…

对抗攻击算法:FGSM和PGD

FGSM 传送门 FGSM 利用了梯度上升的思想&#xff0c;通过损失函数相对于输入图像的梯度来找到 最容易 迷惑网络的方向&#xff0c;并沿着这个方向对图像进行微小的扰动。 FGSM 的基本想法是&#xff0c;沿着这个梯度的符号方向对图像进行微调&#xff0c;以最大化损失函数。具…

Matlab mex- setup报错—错误使用 mex,未检测到支持的编译器...

错误日志&#xff1a; 在使用mex编译时报错提示&#xff1a;错误使用 mex&#xff0c;未检测到支持的编译器。您可以安装免费提供的 MinGW-w64 C/C 编译器&#xff1b;请参阅安装 MinGW-w64 编译器。有关更多选项&#xff0c;请访问https://www.mathworks.com/support/compile…

内网穿透步骤

步骤 第一次需要验证token window和linux的方法不同。 然后 启动 cpolar 服务&#xff1a; 在命令窗口中输入 cpolar.exe htttp 8080&#xff0c;启动内网穿透服务。确保命令窗口保持开启状态&#xff0c;以维持穿透效果。 cpolar.exe hhttp 8080 成功后 注意事项 命令窗口…

系统架构:MVVM

引言 MVVM 全称 Model-View-ViewModel&#xff0c;是在 MVP&#xff08;Model-View-Presenter&#xff09;架构模式基础上的进一步演进与优化。MVVM 与 MVP 的基本架构相似&#xff0c;但 MVVM 独特地引入了数据双向绑定机制。这一创新机制有效解决了 MVP 模式中 Model 与 Vie…

网络协议(TCP/IP模型)

目录 网络初识 网络协议 协议分层 协议拆分 分层 协议分层的优势 1.封装效果 2.解耦合 TCP/IP五层模型 协议之间配合工作&#xff08;详解&#xff09; 网络初识 网络核心概念&#xff1a; 局域网&#xff1a;若干电脑连接在一起&#xff0c;通过路由器进行组网。 …

网络安全之IP伪造

眼下非常多站点的涉及存在一些安全漏洞&#xff0c;黑客easy使用ip伪造、session劫持、xss攻击、session注入等手段危害站点安全。在纪录片《互联网之子》&#xff08;建议搞IT的都要看下&#xff09;中。亚伦斯沃茨&#xff08;真实人物&#xff0c;神一般的存在&#xff09;涉…

软件工程之静态建模

静态模型&#xff1a;有助于设计包、类名、属性和方法特征标记&#xff08;但不是方法体&#xff09;的定义&#xff0c;例如UML类图。 用例的关系&#xff1a; 扩展关系&#xff1a; 扩展关系允许一个用例&#xff08;可选&#xff09;扩展另一个用例&#xff08;基用例&…

JS听到了爆燃的回响

Window对象 BOM&#xff08;浏览器对象模型&#xff09; BOM是浏览器对象模型 Window对象是一个全局对象&#xff0c;也可以说是JS中的顶级对象 像是document、alert()、console.log()都是window的属性 所有通过var定义在全局作用域的变量、函数都会变成window对象的属性和…

【Linux】死锁、读写锁、自旋锁

文章目录 1. 死锁1.1 概念1.2 死锁形成的四个必要条件1.3 避免死锁 2. 读者写者问题与读写锁2.1 读者写者问题2.2 读写锁的使用2.3 读写策略 3. 自旋锁3.1 概念3.2 原理3.3 自旋锁的使用3.4 优点与缺点 1. 死锁 1.1 概念 死锁是指在⼀组进程中的各个进程均占有不会释放的资源…

单片机学习笔记 15. 串口通信(理论)

更多单片机学习笔记&#xff1a;单片机学习笔记 1. 点亮一个LED灯单片机学习笔记 2. LED灯闪烁单片机学习笔记 3. LED灯流水灯单片机学习笔记 4. 蜂鸣器滴~滴~滴~单片机学习笔记 5. 数码管静态显示单片机学习笔记 6. 数码管动态显示单片机学习笔记 7. 独立键盘单片机学习笔记 8…

MyBatis异常体系中ErrorContext和ExceptionFactory原理分析

&#x1f3ae; 作者主页&#xff1a;点击 &#x1f381; 完整专栏和代码&#xff1a;点击 &#x1f3e1; 博客主页&#xff1a;点击 文章目录 exceptions包分包设计ExceptionFactory类介绍为什么使用工厂不是直接new呢&#xff1f;【统一的异常处理机制】【异常的封装与转化】【…

【Canvas与雷达】点鼠标可暂停金边蓝屏雷达显示屏

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>点鼠标可暂停金边蓝屏雷达显示屏 Draft1</title><style typ…

Spark Optimization —— Reducing Shuffle

Spark Optimization : Reducing Shuffle “Shuffling is the only thing which Nature cannot undo.” — Arthur Eddington Shuffle Shuffle Shuffle I used to see people playing cards and using the word “Shuffle” even before I knew how to play it. Shuffling in c…