Qt同一信号与槽函数重复连接
都知道在QT中一个信号可以与多个槽函数连接,一个槽函数也可以与多个信号连接。那么,如果一个信号与一个槽函数多次连接然后发送信号会发生什么呢?编译失败?运行时出现异常?只运行一次槽函数还是会多次运行呢?
看以下代码:
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| class MainWindow : public QMainWindow { Q_OBJECT
public: MainWindow(QWidget *parent = nullptr); ~MainWindow();
public slots: void on_pushButton_clicked(); void signSlot();
public: signals: void sign();
private: Ui::MainWindow *ui; uint8_t flag{0}; };
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); connect(this, &MainWindow::sign, this, &MainWindow::signSlot); connect(this, &MainWindow::sign, this, &MainWindow::signSlot); connect(this, &MainWindow::sign, this, &MainWindow::signSlot); }
MainWindow::~MainWindow() { delete ui; }
void MainWindow::signSlot() { this->flag++; qDebug() << this->flag; }
void MainWindow::on_pushButton_clicked() { emit sign(); }
|
该ui有一个按钮,点击此按钮会发送一个信号,而这个信号与一个槽函数重复连接了三次,运行一下看结果:
可以看到槽函数被运行了三次。***也就是说,如果一个信号与一个槽函数多次连接(假设是n次)的话,在发送信号后,一般槽函数就会被调用多少次(n)***。
如果此时取消信号槽的连接会怎么样呢?
1 2 3 4
| connect(this, &MainWindow::sign, this, &MainWindow::signSlot); connect(this, &MainWindow::sign, this, &MainWindow::signSlot); connect(this, &MainWindow::sign, this, &MainWindow::signSlot); disconnect(this, &MainWindow::sign, this, &MainWindow::signSlot);
|
再点击按钮,什么都不会输出,槽函数未被调用。所以调用disconnect
会把在调用之前指定的信号与槽的连接全部取消掉,而不是只取消一次(就和没有连接过一样)。之后在连接的话,现象依旧。
除了通过disconnect
防止这种情况的发生之外,也可以通过指定连接方式避免:
1 2 3 4 5 6 7 8 9
| qDebug() << connect(this, &MainWindow::sign, this, &MainWindow::signSlot, Qt::UniqueConnection); qDebug() << connect(this, &MainWindow::sign, this, &MainWindow::signSlot, Qt::UniqueConnection); qDebug() << connect(this, &MainWindow::sign, this, &MainWindow::signSlot, Qt::UniqueConnection);
|
此时,只有第一个是连接成功的,所以只执行了一次。再看下面:
1 2 3 4 5 6 7 8 9 10
| qDebug() << connect(this, &MainWindow::sign, this, &MainWindow::signSlot); qDebug() << connect(this, &MainWindow::sign, this, &MainWindow::signSlot, Qt::UniqueConnection); qDebug() << connect(this, &MainWindow::sign, this, &MainWindow::signSlot);
|
可以看到第一,三次全部连接成功。
再试几种情况:
1 2 3 4 5 6 7 8 9
| qDebug() << connect(this, &MainWindow::sign, this, &MainWindow::signSlot, Qt::UniqueConnection); qDebug() << connect(this, &MainWindow::sign, this, &MainWindow::signSlot); qDebug() << connect(this, &MainWindow::sign, this, &MainWindow::signSlot);
|
1 2 3 4 5 6 7 8
| qDebug() << connect(this, &MainWindow::sign, this, &MainWindow::signSlot); qDebug() << connect(this, &MainWindow::sign, this, &MainWindow::signSlot); qDebug() << connect(this, &MainWindow::sign, this, &MainWindow::signSlot, Qt::UniqueConnection);
|
个人看法,可以把Qt::UniqueConnection
理解成一个标志位,在连接信号槽时,如果加了这个标志位,那么QT会检查这对信号槽有没有连接过,连接过,不会去再次连接,没有连接过才会去连接。而不加这个标志位,QT是不会去检查是否连接过的,会直接进行连接。