信号中心的实现及其注意事项。
信号中心
信号中心用来转发单例模式与信号中心1-开头问题中的信号,可大大减少信号的传递次数和函数调用的层数,其实现方式如下所示:
signalcenter.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <QObject>
class SignalCenter : public QObject { Q_OBJECT public: SignalCenter(const SignalCenter&) = delete; SignalCenter(SignalCenter&&) = delete;
SignalCenter& operator=(const SignalCenter&) = delete; SignalCenter& operator=(SignalCenter&&) = delete; static SignalCenter& getInstance() { static SignalCenter instance; return instance; }
private: SignalCenter() = default;
signals: void senderButtonClicked(); };
|
- 该类需继承自
QObject
;
- 使用
Q_OBJECT
宏并定义相关信号。
senderframe.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #include "senderframe.h" #include <QHBoxLayout> #include "signalcenter.h"
SenderFrame::SenderFrame(QWidget *parent) : QFrame(parent) { init(); }
SenderFrame::~SenderFrame() {
}
void SenderFrame::init() { button_ = new QPushButton(u8"发送",this);
QHBoxLayout* hLayout = new QHBoxLayout; hLayout->addWidget(button_);
this->setLayout(hLayout); this->setStyleSheet("background:blue;");
connect(button_, &QPushButton::clicked, &SignalCenter::getInstance(), &SignalCenter::senderButtonClicked); }
|
receiverframe.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include "receiverframe.h" #include <QHBoxLayout> #include "signalcenter.h"
ReceiverFrame::ReceiverFrame(QWidget *parent) : QFrame(parent) { init(); }
ReceiverFrame::~ReceiverFrame() { }
void ReceiverFrame::init() { label_ = new QLabel(this);
QHBoxLayout* hLayout = new QHBoxLayout; hLayout->addWidget(label_);
this->setLayout(hLayout); this->setStyleSheet("background:green;");
connect(&SignalCenter::getInstance(), &SignalCenter::senderButtonClicked, [=]() { static int i = 0;
label_->setText(QString(u8"第%1次点击").arg(++i)); }); }
|
senderframe.cpp
、receiverframe.cpp
中各自与SignalCenter
单例类connect
,借助于SignalCenter
单例类完成了信号的转发;
- 如注释所言,为了演示简单,该例将
connect
写在了类里面,这样会导致该类所有的实例都会connect
,比如ReceiverFrame
类公用,被实例化了两个实例,这样会导致点击一次按钮,两个实例都改变文字。所以将与SignalCenter
单例类的connect
,放到其父控件中更合适。
mainwindow.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include "mainwindow.h" #include "receiverframe.h" #include "senderframe.h" #include <QHBoxLayout> #include <QDateTime>
MainWindow::MainWindow(QWidget *parent) : QDialog(parent) { init(); }
MainWindow::~MainWindow() { }
void MainWindow::init() { auto senderFrame = new SenderFrame(this); auto receiverFrame = new ReceiverFrame(this);
QHBoxLayout* hLayout = new QHBoxLayout; hLayout->setContentsMargins(0, 0, 0, 0); hLayout->setSpacing(20);
hLayout->addWidget(senderFrame); hLayout->addWidget(receiverFrame);
this->setLayout(hLayout); this->setStyleSheet("background:yellow;"); this->setFixedSize(600, 400); }
|
可以看出,在mainwindow.cpp
中只是实例化了SenderFrame
和ReceiverFrame
类,并没有connect
二者,但是信号正常的由SenderFrame
发送到了ReceiverFrame
类。运行结果如下:
