Qt编写自定义控件及插件的使用

2023-05-16

在使用Qt Designer设计窗体界面时,我们可以使用Widget Box里的窗体控件非常方便的绘制界面,比如拖进去一个按钮,一个文本编辑器等。虽然Qt Designer里的控件可以满足我们大部分的需求,但是有时候,也会产生一些特殊的需要,比如一个输入框,我们要输入的是经纬度,此时就会有两种输入方式,一种是小数形式,一种是度分秒的形式,此时只使用一个简单的LineEdit是无法满足需求的。我们设想构造这样一个输入控件,它可以支持浮点数输入,同时它还具有一个属性,更改这个属性可以使其切换为经纬度输入形式。如果我们的多个窗体上都需要输入经纬度,那么构造这样一个控件,将会非常方便。下面就以此为例,讲解一下如何创建自定义的窗体控件。

第一步:创建QtDesigner自定义控件工程

  打开Qt Creator,创建一个Qt 设计师自定义控件,如下图所示:

   根据向导提示,建立一个新类,取名“Test"(注:首字母大写,不能全小写,不然后面会出错),一直点击”下一点“,完成工程创建。

   工程创建完毕,如下图所示:

第二步:编辑工程代码

  在新建的工程中,Test类没有ui界面文件,我们要手动添加上去,如果没有ui界面文件,工程编译也可以通过,但该控件添加到ctreator后,一打开desinger工具的时候就会直接挂掉。所以,我们可以把原先的Test类的test.c和test.h删除掉,重新添加一个Test类。

 

  新建一个Test类,如下:

  为了减少出错机率,此时不对界面做任何动作。

  在工程头文件”test.h“中添加 “#include <QtUiPlugin/QDesignerExportWidget>”,在类名前添加”QDESIGNER_WIDGET_EXPORT“宏。如下图:

 

第三步:编译工程

  保存并选择release方式编译。先qmake一下,

  点击左下角的”构建“按钮,进行编译。

  编译完成。此时会生成testplugin.dll和testplugin.lib两个库。

第四步:部署插件

  编译完成后,在输出目录下,找到对应的testplugin.dll和testplugin.lib两个文件。分别拷贝到QT库的designer路径下和QT的IDE工具的designer路径下。

以我本地5.7.0路径为例:(具体以个人的QT安装路径为准)

QT库的designer库路径:C:\software\GRG\Qt\Qt5.7.0\5.7\msvc2013\plugins\designer

QT库的IDE路径:C:\software\GRG\Qt\Qt5.7.0\Tools\QtCreator\bin\plugins\designer

第五步:测试使用插件

  新建一个工程,在工程使用该Test自定义插件。

  1、打开*.ui,在左下角会出现我们前面编译的自定义插件,如下图:

  直接拖拽到ui界面。

  2、在工程所在文件目录中,新建include文件夹,将前面的插件头文件test.h放在该include文件夹中。新建lib文件夹,将前面生成的testplugin.lib静态库放在此lib文件夹中。

   3、打开测试工程的*.pro文件。添加相应的include路径和lib路径。

添加以下内容:


1 LIBS += $$PWD/lib/testplugin.lib
2 INCLUDEPATH += $$PWD/include  

如下图:

  4、切换到release编译模式,点击qmake,生成相应的makefile文件。并将前面生成的testplugin.dll动态库添加到release输出目录中。如下图:

  5、点击构建,此时会生成*.exe到release输出目录。

 

  此时。直接运行*.exe就可以使用该插件了。自定义插件的新建并使用到此算是OK了。

第六步:Qt自定义插件注意事项:

1:每个Qt库bin目录的designer可执行文件都是和该库同一个编译器编译的,可用,如果想要集成到Qt Creator中,则需要注意版本,一般在windows上的Qt Creator版本是MSVC的,则需要对应的Qt库也是MSVC编译的,库版本和编译器版本必须保持一致才能是顺利集成到Qt Creator的重要前提。

2:自定义控件的名称不能小写,否则拖过去的控件自动生成的默认名称和类名一样,会编译通不过。这个问题坑了我很久,造成自动生成的UI代码保存,一直没有怀疑,后面才发现自动生成的代码类名和实例名称一样,冲突导致的。

3:自定义控件类头文件引入,Qt5.7以下版本为#include <QtDesigner/QDesignerExportWidget> 以上版本为#include <QtUiPlugin/QDesignerExportWidget>

4:类名前必须加入 QDESIGNER_WIDGET_EXPORT 宏。否则集成到Qt Creator 中编译会报错。不加的话可以在设计器中加载,但是编译会报错。

5:如果将生成好的dll文件放到Qt库目录下的 plugins\designer 下,可以在 designer 中看到。放到Qt Creator下的 bin\plugins\designer 则可以集成到Qt Creator中。

6:将自定义控件的头文件、dll文件、lib(mingw编译器为.a)文件复制出来,放到include(可自己随便命名,我这里习惯用include)目录,将include目录放到项目的源码文件下,在使用了自定义控件的项目的pro文件中,增加两行 INCLUDEPATH += $$PWD/include   LIBS += $$PWD/include/***.lib(mingw编译器为.a) ,这样可以正常编译,但是编译完成后不能运行,还需要将 对应自定义控件的dll文件复制到可执行文件同一目录即可,至此大功告成。

番外话:大部分文章介绍都是将对应的库文件和头文件放到Qt安装目录对应文件夹下,为什么这里要放到一个include目录,随着项目一起呢?个人是这么理解的,随项目一起,每次都可以很方便的将运行库文件复制到可执行文件同一目录,而不会忘记从Qt库对应目录找该运行库。而且发布代码的时候也可以有个很好的参考。

7:官网提供的Qt Creator版本基本上是MSVC版本,如果需要在mingw的Qt库对应的Qt Creator中集成自定义控件,需要自己用对应的Qt库编译Qt Creator源码。

 个人总结:

1 如果要在qtcreator的控件界面出现自定义控件,需要按照查看的这个版本(MSVC 2017,32 bit)生成对应的库,生成release版本(只能用release版本)然后放在F:\Qt\Qt5.9.9\Tools\QtCreator\bin\plugins\designer目录中,新建qt项目,可以在qtcreator的设计面中看到对应的控件,

2 使用的时候,需要看选择的构建项目类型,如果选择msvc,release需要使用自定义控件生成的msvc,release版本库,如果选择msvc,debug,则需要使用自定义控件生成的msvc,release版本库,如果选择mingw debug构建,则需要使用自定义控件生成对应的mingw,debug库。使用时必须要将自定义控件对应的.h,静态,动态库都拷贝到对应的使用项目中,在pro文件中添加


LIBS += $$PWD/lib/libmylistviewctrlplugind.a(如果选择msvc构建项目,需要使用lib)  

INCLUDEPATH += $$PWD/include
,并将对应的dll放在执行目录中。
3 如果需要在qt designer中出现对应的控件,需要将对应版本放在对应的desighner中,同样只能用release版本,F:\Qt\Qt5.9.9\5.9.9\mingw53_32\plugins\designer
  

/**********************************************

Qt自定义控件创建和使用
Qt中很方便的是使用各种自定义控件来分模块实现各种子功能,用于实现代码的解耦;
之前在使用Qt 5.12创建自定义控件时,出现了各种问题,多次重装QtCreator和VS,屡次失败,乃至一度放弃。话说写代码很简单,环境的配置却很难,不知道有多少人在各种开发环境的配置时,被这种挫败感打击而放弃;
不死心,从同事的实例中看到了自定义控件的有效实现,亲自实验,确实能用,写个备忘录记录一下;

一、创建自定义控件
1.首先新建项目,选择“其他项目”下的“Qt4设计师自定义控件”

2.新建一个控件类“One Plugin”

3.写入自定义控件的名称以及使用资源文件名称

将会生成一个Qt项目目录

如果想要在UI设计师界面显示自定义控件,需要将OnePlugin项目设置为Release;
OnePlugin.pro内容:

CONFIG      += plugin debug_and_release
TARGET      = $$qtLibraryTarget(onepluginplugin)
TEMPLATE    = lib

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

greaterThan(QT_MAJOR_VERSION, 4) {
    QT += designer
} else {
    CONFIG += designer
}

target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS    += target
#输出dll放置在QtCreator目录路径
message($$target.path)
include(oneplugin.pri)

编译qmake
概要信息中会输出dll拷贝到QtCreator的plugins/designer目录下;

如果编译后在C:/Qt/5.15.2/msvc2019_64/plugins/designer文件夹下没有生产对于的dll;
在项目设置中“构建”Release下的“添加Build步骤”增加“Custom Process Step”

Command设置为“nmake”;Arguments设置为“install”;

清理项目,并重新构建;
可以在C:/Qt/5.15.2/msvc2019_64/plugins/designer文件夹下看到对应的dll出现;

自动生成的oneplugin.h

#ifndef ONEPLUGIN_H
#define ONEPLUGIN_H
#include <QWidget>
class OnePlugin : public QWidget
{
    Q_OBJECT
public:
    OnePlugin(QWidget *parent = 0);
};
#endif // ONEPLUGIN_H

需要修改为

#ifndef ONEPLUGIN_H
#define ONEPLUGIN_H
#include <QWidget>
#include <QtUiPlugin/QDesignerExportWidget>
class QDESIGNER_WIDGET_EXPORT OnePlugin : public QWidget
{
    Q_OBJECT
public:
    OnePlugin(QWidget *parent = 0);
};
#endif // ONEPLUGIN_H

增加了#include <QtUiPlugin/QDesignerExportWidget>和QDESIGNER_WIDGET_EXPORT
QDESIGNER_WIDGET_EXPORT的F1解释为:
This macro is used when defining custom widgets to ensure that they are correctly exported from plugins for use with Qt Designer.
至此,自定义控件算是创建完成;
将onepluginplugin.dll拷贝到Qt Creator的目录下C:\Qt\Tools\QtCreator\bin\plugins\designer,重启QtCreator;
打开ui文件后可以看到自定义控件,不要在意这里面的名字,onePluge是我瞎起的名字;

下面是使用Everything搜索的结果:


二、使用自定义控件
2.1创建测试对话框程序
在测试程序源码文件夹增加lib文件夹,将OnePlugin对应的oneplugin.h和onepluginplugin.lib拷贝到lib文件夹下;
在pro文件内增加
CONFIG += release
HEADERS += lib/
LIBS += $$PWD/lib/onepluginplugin.lib

QT       += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
CONFIG += release
SOURCES += \
    main.cpp \
    widget.cpp
HEADERS += \
    widget.h
FORMS += \
    widget.ui
HEADERS += lib/
LIBS += $$PWD/lib/onepluginplugin.lib
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

在对话框的头文件中增加
#include “lib/oneplugin.h”
Widget类中增加成员变量pOnePlugin;
在构造函数中pOnePlugin = new OnePlugin(this);

#include "lib/oneplugin.h"
class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private:
    Ui::Widget *ui;
    OnePlugin* pOnePlugin;
};

编译程序,出现LNK2019:无法解析的外部符号的错误:

在这停顿了很久,翻了很多百度,发现一个有用的记录;
这里需要将使用到的oneplugin.h中的QDESIGNER_WIDGET_EXPORT删除;
还有一种情况也会出现这种问题,是lib下使用的lib编译类型与当前测试程序的编译类型不相同,重新编译oneplugin项目,将生成的lib拷贝到lib文件夹下;
编译

将dll拷贝到exe的文件夹下;
测试exe可以正常运行

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt编写自定义控件及插件的使用 的相关文章

  • C++类与对象概念详解

    一 简介 1 类用于指定对象的形式 xff0c 它包含了数据表示法和用于处理数据的方法 类中的数据和方法称为类的成员 函数在一个类中被称为类的成员 2 类提供了对象的蓝图 xff0c 所以基本上 xff0c 对象是根据类来创建的 声明类的对
  • C++类对象的创建与释放过程详解

    类的定义与实例化 类对象的创建方法 类对象的创建过程 类对象的释放过程 析构函数 缺省析构函数 类的定义与实例化 类对象的创建方法 1 在栈上创建 类名 对象 无参创建方法 类名 对象 实参 有参创建方法 2 在堆上创建 类名 对象指针 6
  • c++中类创建对象的两种方式

    class A xff1b 1 A a xff1b 2 A a 61 new A 第一种方式对象数据存在栈中 xff0c 是局部变量 xff1b 第二种方式方式申请了动态内存 xff0c 即对象数据在堆区
  • C#里面SQLite读取数据的操作

    挂载表格时候用 public static DataSet Query string SQLString using SQLiteConnection connection 61 new SQLiteConnection connectio
  • C#-Hook钩子实例

    一 写在最前 本文的内容只想以最通俗的语言说明钩子的使用方法 xff0c 具体到钩子的详细介绍可以参照下面的网址 xff1a http www microsoft com china community program originalar
  • C#-invoke与sendmessage,findWindow的阻塞实验

    虽然模态对话框阻塞了顶层窗体 xff0c 但是仍然可以通过findwindow查找顶层窗体句柄 xff0c 并使用sendmessage向顶层窗体发送消息并执行消息内的逻辑 xff08 验证实例如下 xff09 public partial
  • c#中使用Marshal手动在堆中创建非托管内存并使用

    使用 Marshal 做出可以快速释放内存的大数组 需要不断申请一段大内存数组 xff0c 然后就释放他 xff0c 但是 C 对于大内存不是立刻释放 xff0c 所以就存在一定的性能问题 在博客园看到了一位大神使用 Marshal 做出快
  • C#-利用Marshal类实现序列化

    主要是使用Marshal类里的两个方法 xff1a 第一个是StructureToPtr xff0c 将数据从托管对象封送到非托管内存块 第二个是PtrToStructure xff0c 将数据从非托管内存块封送到新分配的指定类型的托管对象
  • c#中事件注册多个委托并获取委托列表

    using System namespace 委托和事件 internal class Program private static void Main string args Action action 61 One action 43
  • vnc怎么注册,教你3步解决vnc怎么注册

    VNC Virtual Network Computing 是一款优秀的远程控制工具软件 xff0c 由著名的AT amp T的欧洲研究实验室开发的 VNC是在基于UNIX和Linux操作系统的免费的开放源码软件 xff0c 远程控制能力强
  • C#中4种深拷贝方法实例

    1 xff1a 利用反射实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static T DeepCopy lt T gt T obj 如果是字符串或值类型则直接返回 if obj is string
  • c#子线程和主线程创建窗体时顶层显示的区别

    主线程 1 设置TopLevel xff0c Topmost bringfront属性 子线程 2 在可在Load事件里注册循环设置TopLevel xff0c Topmost bringTofront属性的方法 xff0c 如下 frm
  • 模态对话框阻塞主线程的话不影响其他线程操作主线程控件(不阻塞)

    Task Factory StartNew 61 gt Thread Sleep 5000 this Invoke new Action 61 gt this button7 Text 61 34 aaaaaaaaaaaaaa 34 Mes
  • Ubuntu18.04.3虚拟机安装步骤图文教程

    虚拟机的安装步骤就不教学了 xff01 自行百度 xff01 接下来 教学ubuntu18 04 3desktop amd64版本的安装和配置教程 软件下载地址详细介绍 xff1a ubuntu 18 04 3 下载速度很快 xff1a 2
  • Linux安装QTCreator问题解决汇总

    关于Ubuntu18版本下新安装Qtcreator编译报错 cannot run compiler clang 43 43 output的解决办法 前两次本以为记住了 xff0c 结果第三次再次在Linux下安装qtcreator依然捣鼓搞
  • Qt路径中常用字符“./”、“../”、“/”、“*”的含义

    在Qt中进行编程时 xff0c 当我们需要调用某些路径时候 xff0c 特别是调用QDir类进行访问时 xff0c 会定义一系列的字符串 xff0c 并将这些字符串赋值给路径 xff0c 这时候就出现了一个问题 xff0c 这些字符串所代表
  • Qt工程pro文件的配置和头文件和库的添加

    Qt开发中 xff0c pro文件是对正工程所有源码 编译 资源 目录等的全方位配置的唯一方式 xff0c pro文件的编写非常重要 xff0c 以下对几个重要项进行说明 xff08 win和linux xff0c mac平台通用配置 xf
  • Qt -线程基础(QThread、QtConcurrent、信号槽等)

    昨晚看Qt的Manual xff0c 突然发现下一个版本的Qt中 Qt4 7 4 Qt4 8等 增加了一个特赞的介绍多线程的文章 xff1a Thread Basics 注意 xff1a 该链接以后会失效 xff0c 但是 到时候你直接看Q
  • Qt中线程同步的几种方法详解

    1 QMutex类 QMutex类就像一把锁 xff0c 在互斥量以前上锁 xff08 QMutex lock xff09 xff0c 而后在使用完互斥量以后解锁 xff08 QMutex unlock xff09 好比下面的代码 xff1
  • Qt中多线程同步总结示例

    1 QMutex QMutex mutex void func mutex lock mutex unlock 2 QMutex联手QMutexLocker 在复杂函数或者异常处理中 xff0c 对mutex进行lock 和unlock 操

随机推荐

  • vnc远程连接ubuntu,如何实现vnc远程连接ubuntu教程图解

    Ubuntu Linux是由南非人马克 沙特尔沃思 Mark Shuttleworth 创办的基于Debian Linux的操作系统 Ubuntu几乎包含了所有常用的应用软件 xff1a 文字处理 电子邮件 软件开发工具和Web服务等 用户
  • 什么是元学习?

    作者 Aleksandr Movchan 编译 VK 来源 Medium 人工智能的一个基本问题是它无法像人类一样高效地学习 许多深度学习分类器显示了超人的表现 xff0c 但需要数百万个训练样本 知识不共享 xff0c 并且每个任务都独立
  • Qt-多线程-QThread分析总结

    QThread是Qt提供的线程类 xff0c 每一个QThread均可管理一个线程 其具有两种使用方式 xff1a 1 继承为QThread的子类 xff1b 2 继承为QObject的子类 xff0c 并使用QObject moveToT
  • C++中 二重指针详解

    前言 上篇博文讲到数组和指针的一些关系 xff0c 本篇博文会在这基础之上讲解一些更为复杂的指针 xff0c 这些指针在笔试题中经常出现 xff0c 对刚毕业找工作的大学生有很大的作用 指向指针的指针 在指针篇 xff08 1 xff09
  • C++中数组初始化方法

    定义 xff1a int pia 61 new int 10 array of 10 uninitialized ints 此 new 表达式分配了一个含有 10 个 int 型元素的数组 xff0c 并返回指向该数组第一个元素的指针 xf
  • 类对象的内存和堆空间的内存及初始化详解

    对象的内存 对象的内存可以存在于 3 种地方 xff1a 全局区 xff08 数据段 xff09 xff1a 全局变量栈空间 xff1a 函数里面的局部变量堆空间 xff1a 动态申请内存 xff08 malloc new等 xff09 文
  • C++内存空间管理

    1 C 43 43 内存机制 1 栈 Stack xff0c 函数中的局部变量 xff0c 由编译器负责分配释放 xff0c 函数结束 xff0c 变量释放 2 堆 Heap xff0c 通过new 申请的内存 xff0c 由delete或
  • Qt中跨线程下信号和槽的使用方法

    connect用于连接qt的信号和槽 xff0c 在qt编程过程中不可或缺 它其实有第五个参数 xff0c 只是一般使用默认值 xff0c 在满足某些特殊需求的时候可能需要手动设置 Qt AutoConnection xff1a 默认值 x
  • Qt 中开启线程的多种方式小结

    简介1 继承 QThread 重写 run 函数2 继承 QObject 调用 moveToThread3 继承 QRunnable 重新 run 函数 xff0c 结合 QThreadPool 实现线程池4 使用 C 43 43 11 中
  • Qt中exec函数的作用

    Qt中的exec 方法到处可见 xff0c 例如 xff1a QCoreApplicaton exec QApplication exec QDialog exec QThread exec QMenu exec 那么 xff0c 这些ex
  • 在Qt中使用全局变量的两种方式,及出现无法解析的命令的问题

    很多小伙伴在Qt编程时 xff0c 不会使用全局变量 xff0c 其实基本有两种方式来定义使用全局变量 xff0c 第一种是根据c c 43 43 的extern来进行多文件的使用 xff0c 第二种方法就是把全局变量放在类中 xff0c
  • Qt中信号槽形参值传递,引用传递,指针传递的实例及总结

    在同一个线程中 当信号和槽都在同一个线程中时 xff0c 值传递参数和引用传递参数有区别 xff1a 值传递会复制对象 xff1b xff08 测试时 xff0c 打印传递前后的地址不同 xff09 引用传递不会复制对象 xff1b xff
  • vnc远程连接,5个步骤教你如何轻松实现vnc远程连接

    当我们在进行vnc远程连接时 xff0c 往往找不到有用的工具来支撑我们的工作 那当我们在进行vnc远程连接时 xff0c 有什么工具能让我们快速实现vnc远程连接呢 xff1f iis7服务器管理工具 如图 xff1a IIS7服务器管理
  • 关于qt信号槽传指针与释放指针

    今天 xff0c 意外发现qt中信号槽传指针的方式进行时 xff0c 会发生释放不掉指针所分配的空间的情况 定义一个信号 void emit showTime Data 槽 void slot showTime Data 在发出信号之前动态
  • Qt-信号和槽函数传递自定义参数前需注册自定义数据类型

    Qt 信号和槽函数参数只能是基于 Qt 的基础类型的 xff0c 比如 QString int bool 等 xff0c 如果想传递自定义类型默认情况下是行不通的 要想在 Qt 的信号和槽函数之间传递自定义类型 xff0c 可以先将自己的自
  • Qt 设置窗口背景图片的几种方法实例

    1 在paintEvent事件中绘制图片 void Widget paintEvent QPaintEvent ev QPainter painter this painter drawPixmap rect QPixmap 34 bg j
  • Qt事件处理的几种方式

    Qt提供了5种事件处理和事件过滤的方法 xff1a 1 重写事件处理器函数 这是大部分情况最常用的一种 xff0c 如重写 paintEvent mousePressEvent keyPressEvent 等事件处理器虚函数 2 重写 QO
  • QT中添加图片资源的方法

    1 在ui设计界面中添加label xff0c 用于显示图片 2 添加QT资源文件 往项目中添加新文件 xff0c 选择QT分类中的资源文件 xff0c 名称为 34 myImage 34 其他选项默认 3 添加资源 在项目目录下新建文件夹
  • Q_OBJECT的作用

    只有继承了QObject类的类 xff0c 才具有信号槽的能力 所以 xff0c 为了使用信号槽 xff0c 必须继承QObject 凡是QObject类 xff08 不管是直接子类还是间接子类 xff09 xff0c 都应该在第一行代码写
  • Qt编写自定义控件及插件的使用

    在使用Qt Designer设计窗体界面时 xff0c 我们可以使用Widget Box里的窗体控件非常方便的绘制界面 xff0c 比如拖进去一个按钮 xff0c 一个文本编辑器等 虽然Qt Designer里的控件可以满足我们大部分的需求