Qt不同窗口类的控件信号和槽绑定

做项目的时候我使用了Qt,不同的界面使用了不同的ui的类进行解耦,但是信号和槽绑定的时候可能是不同界面的控件互相进行通讯连接,然而ui指针对于各个界面类是私有成员,无法直接跳过访问,在网上看了一些参考资料,感觉都不太好,以下是几种可行的方案:

  1. 把ui成员变成一个public成员,但这样不仅破坏了封装性,而且把所有的ui成员全部暴露出去了。
  2. 使用一个static指针来将当前的界面指针传到外面,但是如果多个界面都要这样设计指针满天飞感觉非常的凌乱。
  3. 使用类似职责链模式将信号和槽进行一层层传递,但是要写很多层,太麻烦了。

思来想去,我想了一个解决办法,我们需要的是控件的指针,那么不妨直接用一个类管理这些指针,就可以最小化暴露指针成员。具体的思路是这样的:使用一个哈希表,键自己定,值是一个控件的指针,为了所有的控件都可以放入哈希表,哈希表的值设置为void*,取出来的时候用户再自己进行强转。

  • SignalSlotObjectMap.h
cpp 复制代码
#ifndef SIGNAL_SLOT_OBJECT_MAP_H
#define SIGNAL_SLOT_OBJECT_MAP_H
#include <QString>
#include <QMap>
class SignalSlotObjectMap
{
public:
    static void InsertSignalObjectMap(const QString &key, void *value);
    static void InsertSlotObjectMap(const QString &key, void *value);
    static void *FindSignalObjectMap(const QString &key);
    static void *FindSlotObjectMap(const QString &key);
    static void DebugPrintMap(void);

private:
    static QMap<QString, void *> s_signalObjectMap;
    static QMap<QString, void *> s_slotObjectMap;
};

#endif // SIGNAL_SLOT_OBJECT_MAP_H
  • SignalSlotObjectMap.cpp
cpp 复制代码
#include "SignalSlotObjectMap.h"
#include <QDebug>
// 初始化静态成员变量
QMap<QString, void *> SignalSlotObjectMap::s_signalObjectMap = {};
QMap<QString, void *> SignalSlotObjectMap::s_slotObjectMap = {};

void SignalSlotObjectMap::InsertSignalObjectMap(const QString &key, void *value)
{
    auto it = s_signalObjectMap.find(key);
    if (it != s_signalObjectMap.end())
        return;
    s_signalObjectMap.insert(key, value);
}

void SignalSlotObjectMap::InsertSlotObjectMap(const QString &key, void *value)
{
    auto it = s_slotObjectMap.find(key);
    if (it != s_slotObjectMap.end())
        return;
    s_slotObjectMap.insert(key, value);
}

void *SignalSlotObjectMap::FindSignalObjectMap(const QString &key)
{
    auto it = s_signalObjectMap.find(key);
    if (it != s_signalObjectMap.end())
        return it.value();
    return nullptr;
}

void *SignalSlotObjectMap::FindSlotObjectMap(const QString &key)
{
    auto it = s_slotObjectMap.find(key);
    if (it != s_slotObjectMap.end())
        return it.value();
    return nullptr;
}

void SignalSlotObjectMap::DebugPrintMap(void)
{
    qDebug() << "s_signalObjectMap:";
    for (auto it = s_signalObjectMap.begin(); it != s_signalObjectMap.end(); it++)
    {
        qDebug() << "key:" << it.key() << ",value:" << it.value();
    }
    qDebug() << "s_slotObjectMap:";
    for (auto it = s_slotObjectMap.begin(); it != s_slotObjectMap.end(); it++)
    {
        qDebug() << "key:" << it.key() << ",value:" << it.value();
    }
}

在我的场景里我想将mainWindow的OpenGLWidget发送的【信号 】连接到mainWindow的tabView(我自己定义的一个继承自QWidget的类)的SimSettingWidget(也是我自己定义的一个继承自QWidget的类)的一个lineEdit_Fps控件【】显示我的帧率,首先先统一插入到静态的Slot哈希表,这写在SimSettingWidget的构造函数里

cpp 复制代码
SimSettingWidget::SimSettingWidget(QWidget *parent) : QWidget(parent),
                                                      ui(new Ui::SimSettingWidget)
{
    ui->setupUi(this);
    SignalSlotObjectMap::InsertSlotObjectMap("lineEditFps", static_cast<void *>(ui->lineEdit_Fps));
}

这样mainWindow里把这个指针取出来就行了:

cpp 复制代码
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
                                          ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 其他程序
    QLineEdit *lineEditFps = static_cast<QLineEdit *>(SignalSlotObjectMap::FindSlotObjectMap("lineEditFps"));
    connect(ui->widget_robotSim, &RobotView::sendFPS, this, [lineEditFps](float currentFPS)
            { lineEditFps->setText(QString("%1").arg(currentFPS)); });
}

这样就统一管理的需要的控件,所有的connect都可以在mainWindow进行,相当于树的根节点,表除了可以插入信号控件的指针,也可以插入槽控件的指针,写起来就比较舒服了。

相关推荐
csdn_zhangchunfeng4 分钟前
Qt之slots和Q_SLOTS的区别
开发语言·qt
Larry_Yanan4 小时前
Qt网络开发之基于 QWebEngine 实现简易内嵌浏览器
linux·开发语言·网络·c++·笔记·qt·学习
一然明月7 小时前
Qt QML 锚定(Anchors)全解析
java·数据库·qt
一只爱学习的小鱼儿7 小时前
使用QT编写粒子显示热力图效果
开发语言·qt
大树学长7 小时前
【QT开发】Redis通信相关(一)
redis·qt
笨笨马甲7 小时前
Qt 人脸识别
开发语言·qt
山上三树8 小时前
Qt QObject介绍
开发语言·qt
山上三树8 小时前
QObject、QWidget、Widget三者的关系
qt
坚定学代码8 小时前
qt c++ 局域网聊天小工具
c++·qt·个人开发
笨笨马甲9 小时前
Qt network开发
开发语言·qt