本帖最后由 baizy77 于 2019-9-2 17:17 编辑
作者: 女儿叫老白 转载请注明出处! ----------------------------------------------------------------
引言 ---------------------------------------------------------------- 前面几个章节中,我们为朋友们介绍了信号槽的绑定,其中包括使用自定义信号以及信号转发。这些内容都用到了connect,本节我们为朋友们讲一下disconnect,也就是解绑(断开连接),到底什么是解绑,为什么要解绑呢?本节为朋友们揭晓答案。
正文 ---------------------------------------------------------------- 通过前面的课程,我们已经知道:将信号与槽绑定时需要调用connect()。而connect时需要提供发送者、接收者的地址。当发送者或者接收者已经不再活动时,我们可能也要将信号、槽解绑,以便将信号、槽绑定到新的活动对象。比如在一个多文档窗口程序中,当在某一个子窗口中选中文本时,我们将该文本内容显示在主窗口下方的状态栏中。这个功能我们可以使用信号槽绑定的方式实现。当我们点击选中子窗口A内的文本时,状态栏应显示A中被选中的文本,当点击选中子窗口B内的文本时,状态栏应显示B中被选中的文本。很明显,要实现该功能,我们就应该在子窗口的文本被选中时发出信号。当然,我们得先定义信号: 代码清单05-04-01 mdichild.h - class MdiChild : public QTextEdit
- {
- // ......
- Q_SIGNALS:
- void textSelected(const QString&);
- };
复制代码 然后在鼠标抬起时发出信号textSelected,见代码清单05-04-02第5行: 代码清单05-04-02
mdichild.cpp - void MdiChild::mouseReleaseEvent(QMouseEvent *e) {
- QTextCursor tc = textCursor();
- QString strSelectedText = tc.selectedText().trimmed();
- emit textSelected(strSelectedText);
-
- QTextEdit::mouseReleaseEvent(e);
- }
复制代码最后,当子窗口被激活时,将被激活的子窗口发出的信号textSelected与主窗口的槽函数进行绑定。 在此之前,我们先要将子窗口激活信号QMdiArea::subWindowActivated绑定到主窗口的槽函数,见代码清单05-04-03第7行: 代码清单05-04-03
mainwindow.cpp - MainWindow::MainWindow()
- : mdiArea(new QMdiArea), m_pLastChild(NULL)
- {
- mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- setCentralWidget(mdiArea);
- connect(mdiArea, &QMdiArea::subWindowActivated,
- this, &MainWindow::slot_SubWindowActivated);
- }
复制代码然后,在该槽函数中将子窗口的信号textSelected与主窗口的槽函数执行绑定操作,见代码清单05-04-04中第3~4行: 代码清单05-04-04
mainwindow.cpp - void MainWindow::slot_SubWindowActivated()
- {
- connect(activeMdiChild(), &MdiChild::textSelected, this,
- &MainWindow::slot_TextSelected);
- }
复制代码在MainWindow的槽函数slot_TextSelected()中: - void MainWindow:: slot_TextSelected(const QString& strTextSelected) {
- statusBar()->showMessage(strTextSelected);
- }
复制代码这样,当子窗口切换后,当选中子窗口中的文本时,主窗口的状态栏就可以显示当前活动子窗口中刚刚被选中的文本。 整个功能似乎开发完毕。当我们切换子窗口时,将新激活的子窗口发出的消息与主窗体的槽函数进行绑定。但是请不要忘记,失去焦点的旧的子窗口之前曾经参与过绑定。如果每次被激活都重新绑定,那么将导致内存泄漏;而且因为多次绑定会导致触发多次槽函数的重复调用,这也是不正确的。正确的做法是每次激活新的子窗口时,应当先把失去焦点的子窗口的信号解绑。为此,我们为主窗口定义一个成员变量m_pLastChild用来保存上次的活动子窗口。因此代码清单05-04-04变成这样: 代码清单05-04-05
mainwindow.cpp - void MainWindow::onSubWindowActivated()
- {
- if (NULL != m_pLastChild) {
- if (activeMdiChild() != m_pLastChild) {
- // 过滤掉最小化后的还原事项或者其他类似事项
- disconnect(m_pLastChild, &MdiChild::textSelected,
- this, &MainWindow::slot_TextSelected);
- connect(activeMdiChild(), &MdiChild::textSelected,
- this, &MainWindow::slot_TextSelected);
- }
- }
- m_pLastChild = activeMdiChild();
- // ……
- }
复制代码在代码清单05-04-05中,我们先用disconnect()解除旧的信号槽绑定,然后用connect()建立新的绑定关系。请注意,disconnect()的语法跟connect一致。
结语 ---------------------------------------------------------------- 本节中,我们给出了需要调用disconnect解除信号槽绑定的一种示例。读者可以根据自己平时工作、学习中的各种业务场景进行灵活处理,在合适的地方执行绑定或解绑操作。
----------------------------------------------------------------
|