Qt学习笔记5-对话框
对话框是 GUI 程序中不可或缺的组成部分。很多不能或者不适合放入主窗口的功能组件都必须放在对话框中设置。对话框通常会是一个顶层窗口,出现在程序最上层,用于实现短期任务或者简洁的用户交互。
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
| MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setWindowTitle(tr("Main Window"));
openAction = new QAction(QIcon(":/images/doc-open"), tr("&Open..."), this); openAction->setShortcuts(QKeySequence::Open); openAction->setStatusTip(tr("Open an existing file")); connect(openAction, &QAction::triggered, this, &MainWindow::open);
QMenu *file = menuBar()->addMenu(tr("&File")); file->addAction(openAction);
QToolBar *toolBar = addToolBar(tr("&File")); toolBar->addAction(openAction); }
MainWindow::~MainWindow() { }
void MainWindow::open() { QDialog *dialog = new QDialog; dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setWindowTitle(tr("Hello, dialog!")); dialog->show(); }
|
防止内存泄漏,同时实现了非模态对话框
对话框的数据传递
对话框的出现用于完成一个简单的或者是短期的任务。对话框与主窗口之间的数据交互相当重要。本节将讲解如何在对话框和主窗口之间进行数据交互。
模态对话框使用了exec()
函数将其显示出来。exec()
函数的真正含义是开启一个新的事件循环。所谓事件循环,可以理解成一个无限循环。Qt 在开启了事件循环之后,系统发出的各种事件才能够被程序监听到。这个事件循环相当于一种轮询的作用。既然是无限循环,当然在开启了事件循环的地方,代码就会被阻塞,后面的语句也就不会被执行到。因此,对于使用了exec()
显示的模态对话框,我们可以再exec()
函数之后直接从对话框的对象获取到数据值。
看一下下面的代码:
1 2 3 4 5 6 7
| void MainWindow::open() { QDialog dialog(this); dialog.setWindowTitle(tr("Hello, dialog!")); dialog.exec(); qDebug() << dialog.result(); }
|
上面的代码中,我们使用exec()
显示了一个模态对话框。最后一行代码,qDebug()
类似于std::cout
或者 Java 的System.out.println();
语句,将后面的信息输出到标准输出,一般就是控制台。使用qDebug()
需要引入头文件。在exec()
函数之后,我们直接可以获取到 dialog 的数据值。注意,exec()
开始了一个事件循环,代码被阻塞到这里。由于exec()
函数没有返回,因此下面的result()
函数也就不会被执行。直到对话框关闭,exec()
函数返回,此时,我们就可以取得对话框的数据。
需要注意的一点是,如果我们设置 dialog 的属性为WA_DeleteOnClose
,那么当对话框关闭时,对象被销毁,我们就不能使用这种办法获取数据了。在这种情况下,我们可以考虑使用 parent 指针的方式构建对话框,避免设置WA_DeleteOnClose
属性;或者是利用另外的方式。
实际上,QDialog::exec()
是有返回值的,其返回值是QDialog::Accepted
或者QDialog::Rejected
。一般我们会使用类似下面的代码
1 2 3 4 5 6
| QDialog dialog(this); if (dialog.exec() == QDialog::Accepted) { // do something } else { // do something else }
|
来判断对话框的返回值,也就是用户是点击了“确定”还是“取消”。
由于非模态对话框在关闭时可以调用QDialog::accept()或者QDialog::reject()或者更通用的QDialog::done()函数,所以我们可以在这里发出信号。另外,如果找不到合适的信号发出点,我们可以重写QDialog::closeEvent()函数,在这里发出信号。在需要接收数据的窗口(这里是主窗口)连接到这个信号即可。类似的代码片段如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| //!!! Qt 5 // in dialog: void UserAgeDialog::accept() { emit userAgeChanged(newAge); // newAge is an int QDialog::accept(); }
// in main window: void MainWindow::showUserAgeDialog() { UserAgeDialog *dialog = new UserAgeDialog(this); connect(dialog, &UserAgeDialog::userAgeChanged, this, &MainWindow::setUserAge); dialog->show(); }
// ...
void MainWindow::setUserAge(int age) { userAge = age; }
|