在飞扬青云大佬的文章Qt开发经验里的第82条写道:
代码Qt的信号槽机制非常牛逼,也是Qt的独特的核心功能之一,有时候我们在很多窗体中传递信号来实现更新或者处理,如果窗体层级比较多,比如窗体A的父类是窗体B,窗体B的父类是窗体C,窗体C有个子窗体D,如果窗体A一个信号要传递给窗体D,问题来了,必须先经过窗体B中转到窗体C再到窗体D才行,这样的话各种信号关联信号的connect会非常多而且管理起来比较乱,可以考虑增加一个全局的单例类AppEvent,公共的信号放这里,然后窗体A对应信号绑定到AppEvent,窗体D绑定AppEvent的信号到对应的槽函数即可,干净清爽整洁。
于是想办法写了一个类GlobalMessageHelper 注意这个类用的是单例的设计模式。
验证的思路是写了4个窗口ABCD,其中A点击按钮弹窗D,B点击按钮弹窗C,C里点击按钮将其中LineEdit输入的内容传递到D里去。如果普通的传递路线应该是C->B->main->A->D(当然可以直接C->D,但是如果项目里很多这种跨窗口的消息直接传递,就会形成飞扬大佬提到的复杂情况)。用GlobalMessageHelper 类后,就可以通过它实现所有sender和receiver直接连接。效果可以看下一节
// GlobalMessageHelper h文件 #include#include class GlobalMessageHelper : public QObject { Q_OBJECT public: ~GlobalMessageHelper(); static GlobalMessageHelper *getInstance(); signals: void sendToAFromB(const QString &str); void sendToCFromD(const QString &str); private: GlobalMessageHelper(QObject *parent = nullptr); static GlobalMessageHelper *gMessageHelper; }; // cpp文件 #include "globalmessagehelper.h" GlobalMessageHelper *GlobalMessageHelper::gMessageHelper; GlobalMessageHelper::GlobalMessageHelper(QObject *parent) : QObject{parent} { } GlobalMessageHelper::~GlobalMessageHelper() { } GlobalMessageHelper *GlobalMessageHelper::getInstance() { if (!GlobalMessageHelper::gMessageHelper) GlobalMessageHelper::gMessageHelper = new GlobalMessageHelper; return GlobalMessageHelper::gMessageHelper; }
// DialogA h文件 #include#include #include class DialogA : public QDialog { Q_OBJECT public: DialogA(QDialog *parent = nullptr); }; // DialogA cpp文件 #include "dialoga.h" #include "dialogd.h" #include "globalmessagehelper.h" #include #include #include #include DialogA::DialogA(QDialog *parent) : QDialog(parent) { setWindowTitle("DialogA"); setMinimumSize(QSize(300, 100)); QVBoxLayout *lay = new QVBoxLayout; setLayout(lay); QPushButton *btn = new QPushButton("BTN"); lay->addWidget(btn); connect(btn, &QPushButton::clicked, this, [&]() { DialogD *dlg = new DialogD; dlg->show(); }); }
// DialogB h文件 #include#include class DialogB : public QDialog { Q_OBJECT public: DialogB(QDialog *parent = nullptr); }; // DialogB cpp文件 #include "dialogb.h" #include "dialogc.h" #include #include DialogB::DialogB(QDialog *parent) : QDialog(parent) { setWindowTitle("DialogB"); setMinimumSize(QSize(300, 100)); QVBoxLayout *lay = new QVBoxLayout; setLayout(lay); QPushButton *btn = new QPushButton("BTN"); lay->addWidget(btn); connect(btn, &QPushButton::clicked, this, [&]() { DialogC *dlg = new DialogC; dlg->show(); }); }
// DialogC h文件 #include#include #include class DialogC : public QDialog { Q_OBJECT public: DialogC(QDialog *parent = nullptr); private: QLineEdit *line = nullptr; QPushButton *btn = nullptr; }; // DialogC cpp文件 #include "dialogc.h" #include "globalmessagehelper.h" #include #include #include DialogC::DialogC(QDialog *parent) : QDialog(parent) { setWindowTitle("DialogC"); setMinimumSize(QSize(300, 100)); QVBoxLayout *lay = new QVBoxLayout; setLayout(lay); line = new QLineEdit; lay->addWidget(line); btn = new QPushButton("Send"); lay->addWidget(btn); connect(btn, &QPushButton::clicked, this, [&]() { emit GlobalMessageHelper::getInstance()->sendToAFromB(line->text()); }); }
// DialogD h文件 #include#include class QLineEdit; class DialogD : public QDialog { public: DialogD(); QLineEdit *line = nullptr; }; // DialogD cpp文件 #include "dialogd.h" #include "globalmessagehelper.h" #include #include DialogD::DialogD() { setWindowTitle("DialogD"); setMinimumSize(QSize(300, 100)); QVBoxLayout *lay = new QVBoxLayout; setLayout(lay); line = new QLineEdit; lay->addWidget(line); connect(GlobalMessageHelper::getInstance(), &GlobalMessageHelper::sendToAFromB, this, [&](const QString &s) { Q_ASSERT(GlobalMessageHelper::getInstance() != nullptr); line->setText(s); }); }
// main.cpp 文件 #include "globalmessagehelper.h" #include "dialoga.h" #include "dialogc.h" #include "dialogb.h" #include结果int main(int argc, char *argv[]) { QApplication a(argc, argv); DialogA dlgA; DialogB dlgB; dlgA.show(); dlgB.show(); return a.exec(); }



