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_OBJECTQ_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. herem_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    = libHEADERS     = qwbatteryplugin.h
SOURCES     = qwbatteryplugin.cpp
RESOURCES   = icons.qrc
LIBS        += -L. QT += designertarget.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS    += targetinclude(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_OBJECTQ_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/ -lqwbatteryplugindINCLUDEPATH += $$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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot利用easypoi实现简单导出Excel

vue springboot利用easypoi实现简单导出 前言一、easypoi是什么&#xff1f;二、使用步骤 1.传送门2.前端vue3.后端springboot 3.1编写实体类&#xff08;我这里是dto,也一样&#xff09;3.2控制层结尾 前言 今天玩了一下springboot利用easypoi实现excel的导出&#xff0c;以前…

【学习总结|DAY012】Java面向对象基础

一、前言 今天主要学习了以下内容&#xff1a;面向对象的理解与使用、对象的内存布局、构造器的概念和作用、封装的重要性以及JavaBean实体类的实现等。下面我将详细阐述这些知识点。 二、面向对象的理解与使用 1. 什么是面向对象&#xff1f; 类&#xff1a;一种特殊的数据…

【免费】最新区块链钱包和私钥的助记词碰撞器,bybit使用python开发

使用要求 1、用的是google里面的扩展打包成crx文件&#xff0c;所以在使用之前你需要确保自己电脑上有google浏览器&#xff0c;而且google浏览器版本需要在124之上。&#xff08;要注意一下&#xff0c;就是电脑只能有一个Chrome浏览器&#xff09; 2、在win10上用vscode开发…

【AI模型对比】AI新宠Kimi与ChatGPT的全面对比:技术、性能、应用全揭秘

文章目录 Moss前沿AI技术背景Kimi人工智能的技术积淀ChatGPT的技术优势 详细对比列表模型研发Kimi大模型的研发历程ChatGPT的发展演进 参数规模与架构Kimi大模型的参数规模解析ChatGPT的参数体系 模型表现与局限性Kimi大模型的表现ChatGPT的表现 结论&#xff1a;如何选择适合自…

C#实时监控指定文件夹中的动态,并将文件夹中生成的新图片显示在界面上(相机采图,并且从本地拿图)

结果展示 此类原理适用于文件夹中自动生成图片&#xff0c;并提取最新生成的图片将其显示&#xff0c; 如果你是相机采图将其保存到本地&#xff0c;可以用这中方法可视化&#xff0c;并将检测的结果和图片匹配 理论上任何文件都是可以监视并显示的&#xff0c;我这里只是做了…

Unity性能优化---动态网格组合(二)

在上一篇中&#xff0c;组合的是同一个材质球的网格&#xff0c;如果其中有不一样的材质球会发生什么&#xff1f;如下图&#xff1a; 将场景中的一个物体替换为不同的材质球 运行之后&#xff0c;就变成了相同的材质。 要实现组合不同材质的网格步骤如下&#xff1a; 在父物体…

深入解析Spring AI框架:在Java应用中实现智能化交互的关键

众所周知&#xff0c;Java是一种面向对象的编程语言&#xff0c;因此不论我们调用什么AI接口&#xff0c;从业务的角度来看&#xff0c;它本质上只是一个接口&#xff0c;而AI则充当了一个第三方对接平台。然而&#xff0c;值得注意的是&#xff0c;AI的聊天回复往往不适用于对…

idea 自动导包,并且禁止自动导 *(java.io.*)

自动导包配置 进入 idea 设置&#xff0c;可以按下图所示寻找位置&#xff0c;也可以直接输入 auto import 快速定位到配置。 Add unambiguous imports on the fly&#xff1a;自动帮我们优化导入的包Optimize imports on the fly&#xff1a;自动去掉一些没有用到的包 禁止导…

基于C++实现的(控制台)双人俄罗斯方块小游戏

基于win32控制台应用程序的双人俄罗斯方块小游戏 1. 课题概述 1.1 课题目标和主要内容 使用visual studio 2015在win32控制台应用程序下用多线程实现双人同时进行俄罗斯方块的桌面游戏。最终将要完成的效果如图1.1所示&#xff0c;左右共两片工作区&#xff0c;也是游戏的主…

Python subprocess.run 使用注意事项,避免出现list index out of range

在执行iOS UI 自动化专项测试的时候&#xff0c;在运行第一遍的时候遇到了这样的错误&#xff1a; 2024-12-04 20:22:27 ERROR conftest pytest_runtest_makereport 106 Test test_open_stream.py::TestOpenStream::test_xxx_open_stream[iPhoneX-xxx-1-250] failed with err…

力扣1401. 圆和矩形是否有重叠

用矢量计算&#xff1a; class Solution { public:bool checkOverlap(int radius, int xCenter, int yCenter, int x1, int y1, int x2, int y2) {//矩形中心float Tx(float)(x1x2)/2;float Ty(float)(y1y2)/2;//强行进行对称操作&#xff0c;只考虑第一象限if(xCenter<Tx)…

信号和槽思维脑图+相关练习

将登录框中的取消按钮使用信号和槽的机制&#xff0c;关闭界面。 将登录按钮使用信号和槽连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是否为"123456",如果账号密码匹配成功&#xff0c;当前界面关…

第一部分:基础知识 2. SQL基础 --[MySQL轻松入门教程]

第一部分:基础知识 2. SQL基础 --[MySQL轻松入门教程] SQL(Structured Query Language)是一种用于管理和处理关系型数据库的标准语言。它被广泛应用于各种数据库系统,如MySQL, PostgreSQL, Oracle, SQL Server等。下面是一些SQL的基础知识和常用操作示例。 1.SQL简介 SQ…

《Clustering Propagation for Universal Medical Image Segmentation》CVPR2024

摘要 这篇论文介绍了S2VNet&#xff0c;这是一个用于医学图像分割的通用框架&#xff0c;它通过切片到体积的传播&#xff08;Slice-to-Volume propagation&#xff09;来统一自动&#xff08;AMIS&#xff09;和交互式&#xff08;IMIS&#xff09;医学图像分割任务。S2VNet利…

源码可运行-PHP注册登录源码,PHP实现登陆后才能访问页面

最近有一个项目需要实现会员注册和页面登陆后才能访问&#xff0c;所以简单的HTML是无法实现的&#xff0c;就必须通过PHP、html和Mysql来实现&#xff0c;先给大家看一下登录和注册页的效果图。&#xff08;注册完成后会自动跳转到登录窗口&#xff0c;即使A用户登陆后分享了网…

性能测试常见面试问题和答案

一、有没有做过性能测试&#xff0c;具体怎么做的 性能测试是有做过的&#xff0c;不过我们那个项目的性能做得不多&#xff0c;公司要求也不严格。一般SE 给我们相关的性能需求&#xff0c;首先我们需要对性能需求进行场景分析与设计&#xff0c;这里&#xff0c;其实主要就是…

二百七十八、ClickHouse——将本月第一天所在的那一周视为第一周,无论它是从周几开始的,查询某个日期是本月第几周

一、目的 ClickHouse指标表中有个字段week_of_month&#xff0c;含义是这条数据属于本月第几周。 而且将本月第一天所在的那一周视为第一周&#xff0c;无论它是从周几开始的。比如2024-12-01是周日&#xff0c;即12月第一周。而2024-12-02是周一&#xff0c;即12月第二周 二…

【OCR】——端到端文字识别GOT-OCR2.0不香嘛?

代码&#xff1a;https://github.com/Ucas-HaoranWei/GOT-OCR2.0?tabreadme-ov-file 在线demo&#xff1a;https://huggingface.co/spaces/stepfun-ai/GOT_official_online_demo 0.前言 最早做ocr的时候&#xff0c;就在想如何能做一个端到端的模型&#xff0c;就不用先检测再…

AndroidStudio-常见界面控件

一、Button package com.example.review01import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Button import android.widget.TextViewclass Review01Activity : AppCompatActivity() {override fun onCreate(savedInstanceStat…

网络安全中的 SOC 是什么?

当今世界&#xff0c;网络威胁日益增多&#xff0c;确保网络安全已成为各种规模企业的首要任务。网络安全讨论中经常出现的一个术语是 SOC&#xff0c;即安全运营中心的缩写。但网络安全中的 SOC 是什么呢&#xff1f; SOC在防御网络威胁、管理安全事件和全天候监控系统方面发…