baizy77 发表于 2019-9-2 16:51:22

KS05-04 信号-槽: disconnect的用途

本帖最后由 baizy77 于 2019-9-2 17:17 编辑

该文章原创于Qter开源社区(www.qter.org)作者: 女儿叫老白转载请注明出处!----------------------------------------------------------------

[*]网页版课程源码 提取码:1uy7
[*]免费版视频教程

引言----------------------------------------------------------------    前面几个章节中,我们为朋友们介绍了信号槽的绑定,其中包括使用自定义信号以及信号转发。这些内容都用到了connect,本节我们为朋友们讲一下disconnect,也就是解绑(断开连接),到底什么是解绑,为什么要解绑呢?本节为朋友们揭晓答案。
正文----------------------------------------------------------------    通过前面的课程,我们已经知道:将信号与槽绑定时需要调用connect()。而connect时需要提供发送者、接收者的地址。当发送者或者接收者已经不再活动时,我们可能也要将信号、槽解绑,以便将信号、槽绑定到新的活动对象。比如在一个多文档窗口程序中,当在某一个子窗口中选中文本时,我们将该文本内容显示在主窗口下方的状态栏中。这个功能我们可以使用信号槽绑定的方式实现。当我们点击选中子窗口A内的文本时,状态栏应显示A中被选中的文本,当点击选中子窗口B内的文本时,状态栏应显示B中被选中的文本。很明显,要实现该功能,我们就应该在子窗口的文本被选中时发出信号。当然,我们得先定义信号:代码清单05-04-01mdichild.hclass MdiChild : public QTextEdit
{
    // ......
Q_SIGNALS:
      void textSelected(const QString&);
};
    然后在鼠标抬起时发出信号textSelected,见代码清单05-04-02第5行:代码清单05-04-02
mdichild.cppvoid 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.cppMainWindow::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.cppvoid 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.cppvoid 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解除信号槽绑定的一种示例。读者可以根据自己平时工作、学习中的各种业务场景进行灵活处理,在合适的地方执行绑定或解绑操作。

----------------------------------------------------------------课程目录: 《Qt入门与提高-GUI产品开发》目录
上一节:KS05-03 信号-槽:自定义signal与信号转发下一节:KS05-05 信号-槽:消息阻塞-防止额外触发槽函数
页: [1]
查看完整版本: KS05-04 信号-槽: disconnect的用途