在Qt界面开发过程中,一个主界面或者主窗口看成是各个控件排列组合后的集合,对于一些项目而言,有些常用的控件可以封装成自己想要的控件样式并且复用,比如说,log显示控件,图像/视频显示控件等,可以将常用的控件代码封装起来,以便下次复用,内嵌在不同的主界面内。这里总结了常见的四种方法供大家参考;
头文件为
#include "CustomWidget.h" //自定义控件
class MainWindows : public QMainWindow
{
Q_OBJECT
public:
MainWindows(QWidget *parent = Q_NULLPTR);
private:
CustomWidget *customWidget; //自定义控件
Ui::MainWindowsClass ui;
};
cpp文件内
#include "MainWindows.h"
MainWindows::MainWindows(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
//加载自定义控件
customWidget = new CustomWidget;
ui.layout->addWidget(customWidget);
//调用自定义控件的接口
customWidget->setText();
}
主界面控制自定义控件:可以在子界面内建立一个数据接口函数,这样可以通过直接调用子界面类对象的函数,实现子界面内数据变化;比如说上述,自定义控件的接口setText()可以实现自定义控件的ui刷新;
自定义控件内数据传给主界面:通过信号槽的方式;
#include
#include "ui_CustomWidget.h"
//没有Q_DECL_EXPORT,就不会生成lib文件
class Q_DECL_EXPORT CustomWidget : public QWidget
{
Q_OBJECT
public:
CustomWidget(QWidget *parent = Q_NULLPTR);
void setText(QString str); //接口函数
private:
Ui::CustomWidgetClass ui;
public slots:
void on_openBtn();
};
发布的.h文件为
#include
#include "ui_CustomWidget.h"
//发布时,去掉Q_DECL_EXPORT
class CustomWidget : public QWidget
{
}
#include "CustomWidget.h" //自定义控件
#include
#include
#include "ui_MainWindows.h"
在主界面的Qt Designer中先新建一个QWidget控件,提升控件;选中控件,选择提升为
手动填入自定义控件类的类名称
可以在对象查看器中看到QWidget已经变成了CustomWidget,同时修改对象名称为customWidget,接下来便可以按照第一种方法,在主界面函数类访问自定义控件的数据;
这里我们讲述的自定义控件是制作成插件的方式,因此设计阶段是需要ui文件的,这里需要在项目文件内自行创建一个ui文件。并且在CustomWidget.h内添加ui文件生成的ui_CustomWidget.h头文件。自行添加槽函数,ui对象等;
#pragma once
#include
//自行添加ui生成的头文件
#include "ui_CustomWidget.h"
class CustomWidget : public QWidget
{
Q_OBJECT
public:
CustomWidget(QWidget *parent = Q_NULLPTR);
//自行添加ui界面的信号槽函数
public slots:
void on_openBtn();
//这里要跟ui_CustomWidget.h里面命名空间内的界面类对应上,自行添加
private:
Ui::Form ui;
};
#include "CustomWidget.h"
CustomWidget::CustomWidget(QWidget *parent)
: QWidget(parent)
{
//自行添加的代码
ui.setupUi(this);
connect(ui.openBtn,&QPushButton::clicked,this,&CustomWidget::on_openBtn);
}
//自行添加槽函数
void CustomWidget::on_openBtn()
{
ui.textBrowser->append("open widget");
}
可以看出,插件类CustomWidgetPlugin组合类CustomWidget,CustomWidget组合界面类Form;
在自定义插件的生成文件内可以看到:
自定义插件生成dll和lib文件;主界面动态加载dll文件即可;
//插件的头文件
#include "CustomWidget.h"
#include "ui_CustomWidget.h"
//相应的头文件
#include
#include
动态加载代码为:
QPluginLoader loader("CustomWidget.dll");
if (loader.load())
{
QObject *plugin = loader.instance();
if (plugin)
{
QDesignerCustomWidgetInterface *widget = qobject_cast<QDesignerCustomWidgetInterface *>(plugin);
if (widget)
{
//创建的子控件对象
QWidget *customWidget = widget->createWidget(nullptr);
ui.layout->addWidget(customWidget);
}
}
}
其实四种方法的本质是将自定义控件封装成一个专门的类,通过调用子控件类对象便可以实现内嵌自定义控件,在开发过程中,使用以上四种方法,相当于把界面分成了各个子模块,主界面通过调用这些子模块,可以实现团队之间快速开发工作;
从主界面传递数据到嵌入的自定义子控件,可以通过直接调用子控件类的接口函数实现从主窗口到子窗口之间的数据传递;而子界面传递到主界面或者子界面之间的数据交互可以按照单例模式,建立一个传递信号的类。其本质是建立一个类,通过connect函数可以传递信号到信号,从而实现自定义控件到主界面之间的数据交互;此代码参考的博主文章为:
Qt 信号在多层次对象间传递 多层嵌套类对象之间信号传递
头文件为:
#include
class TransmitSignals : public QObject
{
Q_OBJECT
public:
static TransmitSignals &GetInstance();
private:
TransmitSignals();
~TransmitSignals();
TransmitSignals(const TransmitSignals &) = delete;
TransmitSignals(const TransmitSignals &&) = delete;
TransmitSignals &operator=(const TransmitSignals &) = delete;
signals:
//传递数据
//传给A界面数据
void sigToAWidget(QString ret);
//传给B界面数据
void sigToBWidget(QString ret);
public slots:
};
.cpp文件为
#include "TransmitSignals.h"
TransmitSignals::TransmitSignals()
{
}
TransmitSignals::~TransmitSignals()
{
}
TransmitSignals& TransmitSignals::GetInstance()
{
static TransmitSignals RobotControl;
return RobotControl;
}
上述方法的源代码已放置链接中,可下载后查看项目源码:
Qt主界面内嵌自定义控件的四种方法以及不同控件数据交互