当用户操作在每个运行时初始化应用程序数据时,我有一个用例。为了表示这种行为,我的示例代码为:
SignalSlotChange.h
#ifndef SIGNALSLOTCHANGE_H
#define SIGNALSLOTCHANGE_H
#include <QtGui>
class SignalSlotChange : public QWidget
{
Q_OBJECT
public:
SignalSlotChange(QWidget *parent = 0);
private slots:
void firstCall();
void secondCall();
private:
QPushButton *button;
};
#endif // SIGNALSLOTCHANGE_H
SignalSlotChange.cpp
#include "SignalSlotChange.h"
SignalSlotChange::SignalSlotChange(QWidget *parent) : QWidget(parent)
{
button = new QPushButton("Messgage", this);
QObject::connect(button, SIGNAL(clicked()), this, SLOT(firstCall()));
show();
}
void SignalSlotChange::firstCall()
{
QMessageBox::information(this, "SignalSlotChange", "First call", QMessageBox::Ok, QMessageBox::NoButton);
// Change the signal-slot connection to secondCall()
QObject::disconnect(button, SIGNAL(clicked()), this, SLOT(firstCall()));
QObject::connect(button, SIGNAL(clicked()), this, SLOT(secondCall()));
}
void SignalSlotChange::secondCall()
{
QMessageBox::information(this, "SignalSlotChange", "Second call", QMessageBox::Ok, QMessageBox::NoButton);
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
SignalSlotChange ssc;
return app.exec();
}
按下按钮后,将调用初始化插槽firstCall()
。对于后续信号,它将信号槽连接更改为secondCall()
。
我这样做的问题在于它是高度耦合的,并且要求插槽知道确切的方法和信号来改变它。
使用QObject::sender()
我会知道发件人的来源但不知道它的信号,我会知道只有一个发件人碰巧发出了这个信号。
我可以用布尔值first_call
来做,但这会检查所有后续调用的布尔值,这是我想要避免的,因此这个问题。
答案 0 :(得分:1)
使用指向成员的方法可以实现一个稍微不同的解决方案:
<强> SignalSlotChange.h 强>
#ifndef SIGNALSLOTCHANGE_H
#define SIGNALSLOTCHANGE_H
#include <QtGui>
class SignalSlotChange : public QWidget {
Q_OBJECT
public:
SignalSlotChange(QWidget *parent = 0);
private slots:
void callCall();
private:
void (SignalSlotChange::* delegate) ();
void firstCall();
void secondCall();
QPushButton *button;
};
#endif // SIGNALSLOTCHANGE_H
<强> SignalSlotChange.cpp 强>
#include "SignalSlotChange.h"
SignalSlotChange::SignalSlotChange(QWidget *parent) : QWidget(parent) {
delegate = &SignalSlotChange::firstCall;
button = new QPushButton("Messgage", this);
QObject::connect(button, SIGNAL(clicked()), this, SLOT(callCall()));
show();
}
void SignalSlotChange::callCall() {
(this->*delegate) ();
}
void SignalSlotChange::firstCall() {
QMessageBox::information(this, "SignalSlotChange", "First call", QMessageBox::Ok, QMessageBox::NoButton);
// Change the effective signal-slot connection to secondCall()
delegate = &SignalSlotChange::secondCall;
}
void SignalSlotChange::secondCall() {
QMessageBox::information(this, "SignalSlotChange", "Second call", QMessageBox::Ok, QMessageBox::NoButton);
}
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
SignalSlotChange ssc;
return app.exec();
}
我不确定这是否是从解耦角度来看更好的解决方案,但优点是该机制不需要了解实际触发的插槽的任何信息。实现“方法切换”的完整逻辑封装在SignalSlotChange
类中。 callCall()
插槽可以连接到任何其他兼容信号,方法开关仍可正常工作,无需进一步更改代码。