15、对话框间通信

Par @Martin dans le
Tags :
说明: 这些文章都是本人学习”devbean QT 学习之路2”的笔记, 部分内容摘自原文, 部分是自己的领悟. > >

某些情况下, 项目需求对话框能与父窗口通信, 这在 Qt 中很容易做到.

因为, 对话框分为模态和非模态两种, 所以, 对应的也有两种不同的通信手段.

模态对话框

因为打开模态对话时, 代码会被阻塞住, 所以实时的在父窗口中获取对话框数据几乎是不可能的(或许窗口级别的模态能够实现对话框与非父窗口进行实时通信, 但是对话框与其父窗口应该是不行的).

使用了exec()显示的模态对话框, 可以在exec()函数之后通过 QDialog::result() 直接从对话框对象获取到数据值(当然要先在对话框中用 QDialog::setResult() 来设置数据).

<span style="color: #0000ff">void</span><span style="color: #000000"> MainWindow::open() {
    QDialog dialog(</span><span style="color: #0000ff">this</span><span style="color: #000000">);
    dialog.setWindowTitle(</span><span style="color: #800000">"</span><span style="color: #800000">Hello, dialog!</span><span style="color: #800000">"</span><span style="color: #000000">);
    dialog.exec();
    qDebug() </span><<<span style="color: #000000"> dialog.result();
}</span>

注意使用 Dialog::result() 时, 不能设置 WA_DeleteOnClose 属性, 因为如果设置了这个属性, exec() 返回后, dialog 就会被销毁, 就不可能再获取到数据了. 当然这里也不可能设置 WA_DeleteOnClose 属性, 因为这是模态对话框, 可以直接在栈上创建, 函数返回, 对话框所分配到的内存会自动释放, WA_DeleteOnClose 只有在堆上创建窗口时才使用, 一般用到非模态对话框上.

另外, QDialog::exec()也是有返回值的, 其返回值是 QDialog::Accepted或者 QDialog::Rejected, 这取决于用户点击的是 “OK”还是 “Cancel”按钮(默认情况下, QDialog 有这两个按钮,“OK”被连接到到 accept() 槽, “Cancel”被连接到 reject() 槽), 一般我们会使用类似下面的代码:

QDialog dialog(<span style="color: #0000ff">this</span><span style="color: #000000">);
</span><span style="color: #0000ff">if</span> (dialog.exec() ==<span style="color: #000000"> QDialog::Accepted) {
    </span><span style="color: #008000">//</span><span style="color: #008000"> do something</span>
} <span style="color: #0000ff">else</span><span style="color: #000000"> {
    </span><span style="color: #008000">//</span><span style="color: #008000"> do something else</span>
}

非模态对话框

打开非模态对话框时, 代码是立即返回的, 这也就不可能通过 result() 来获取数据, 要想实现通信, 可以使用信号槽机制.

非模态对话框在关闭时可以调用 QDialog::accept()或者 QDialog::reject()或者更通用的 QDialog::done()函数, 所以就可以在重写这几个函数发出信号; 另外, 如果找不到合适的信号发出点, 还可以重写 QDialog::closeEvent()函数, 在这里发出信号. 在需要接收数据的窗口(这里是主窗口)连接到这个信号即可.

<span style="color: #0000ff">void</span><span style="color: #000000"> UserAgeDialog::accept() {
    emit userAgeChanged(newAge); </span><span style="color: #008000">//</span><span style="color: #008000"> newAge is an int</span>
<span style="color: #000000">    QDialog::accept();
}

</span><span style="color: #008000">//</span><span style="color: #008000"> in main window:</span>
<span style="color: #0000ff">void</span><span style="color: #000000"> MainWindow::showUserAgeDialog() {
    UserAgeDialog </span>*dialog = <span style="color: #0000ff">new</span> UserAgeDialog(<span style="color: #0000ff">this</span><span style="color: #000000">);
    connect(dialog, </span>&UserAgeDialog::userAgeChanged, <span style="color: #0000ff">this</span>, &<span style="color: #000000">MainWindow::setUserAge);
    dialog</span>-><span style="color: #000000">show();
}

</span><span style="color: #008000">//</span><span style="color: #008000"> ...</span>

<span style="color: #0000ff">void</span> MainWindow::setUserAge(<span style="color: #0000ff">int</span><span style="color: #000000"> age) {
    userAge </span>=<span style="color: #000000"> age;
}</span>