Qt学习五 - 对话框

曾经终败给现在 2022-01-07 04:49 508阅读 0赞

一、对话框简介

开发桌面程序,总会需要使用对话框来实现短期任务或者简洁的交互。在Qt中,提供了QDialog类来实现对话框。在QDialog和其子类中,对parent指针有额外的解释:当parent为NULL时,对话框会作为一个顶层窗口,否则则会作为其父组件的子对话框(此时默认显示在父组件的中心位置)。可以新建一个项目,在主窗口上添加一个push button,然后在相应的槽函数中添加如下代码:

  1. QDialog dlg;
  2. dlg.setWindowTitle("hello dialog !");
  3. dlg.exec();

运行程序查看效果,然后将其修改为:

  1. QDialog dlg(this);
  2. dlg.setWindowTitle("hello dialog !");
  3. dlg.exec();

再运行程序,对比两次的差别。

对话框分为模态对话框和非模态对话框两种。模态对话框又分为应用级别的模态对话框和窗口级别的模态对话框。应用级别的模态对话框会阻塞同一应用下的所有窗口,当对话框出现时,用户先要和对话框进行交互,直到对话框关闭才可以和访问其他窗口;窗口级别的模态对话框只会阻塞与对话框相关联的窗口,允许用户与其他窗口进行交互;非模态对话框则与模态对话框相反,它不会阻塞用户与任何窗口的交互。

Qt中,实现应用级别的模态对话框使用QDialog::exec()函数,例如我们上面写的代码,实现窗口级别的模态对话框使用QDialog::open()函数,实现非模态对话框使用QDialog::show()函数。将上面的代码改为非模态对话框方式:

  1. QDialog dlg;
  2. dlg.setWindowTitle("hello dialog !");
  3. dlg.show();

运行发现对话框一闪而过,这是因为对话框创建在栈上,并且show()函数不会阻塞当前线程,对话框显示后代码会继续向下执行,当执行完按钮的槽函数后,超出对话框的作用域,对话框就被析构了。所以需要将对话框创建在堆上,如下:

  1. QDialog* dlg = new QDialog;
  2. dlg->setWindowTitle("hello dialog !");
  3. dlg->show();

创建在堆上就会涉及到释放内存,我们可以指定对话框的parent 为主窗口

  1. QDialog* dlg = new QDialog(this);

但是这样如果主窗口不关闭,dialog就不会被销毁,内存会一直被占用。并且QWidget类的parent只能是QWidget的指针,如果对话框不是显示在界面类上怎么办?针对这个问题,我们可以设置QDialog的WindowAttribute

  1. QDialog* dlg = new QDialog;
  2. dlg->setWindowTitle("hello dialog !");
  3. dlg->setAttribute(Qt::WA_DeleteOnClose);
  4. dlg->show();

这样当对话框关闭时会自动销毁,QObject类还有一个deleteLater()函数,该函数会在事件循环结束后销毁该对话框。

二、对话框数据传递

从模态对话框获取数据:

  1. QDialog dlg;
  2. dlg.exec();
  3. qDebug() << dlg.result();

运行后,不会获取到结果,这是因为exec()(开启一个事件循环)会阻塞当前线程,当关闭对话框exec()函数返回时才会执行下面的代码,才可以获取到数据。如果设置了WA_DeleteOnClose,那么当对话框关闭时就会被销毁,就不能用这种方法获取数据了。exec()函数有两个返回值:QDialog::Accepted和QDialog::Rejected,通常我们会使用类似下面的代码:

  1. QDialog dlg;
  2. if (dlg.exec() == QDialog::Accepted)
  3. {
  4. //do something
  5. }
  6. else
  7. {
  8. //do something
  9. }

从非模态对话框获取数据:

因为QDialog::show()函数不会阻塞线程,show()会立即返回,所以不能通过上面的方式来获取数据,否则不等用户输入,已经执行了下面的代码。我们可以使用信号和槽机制,来获取数据。非模态对话框在关闭时可以调用QDialog::accept()或者QDialog::reject或者QDialog::done()函数,所以我们可以重写QDialog::accept()函数,在这里发送信号。也可以重写QDialog::closeEvent()函数来发送信号。然后在需要接受数据的窗口链接这个信号即可。

在QDialog子类中:

  1. void UserAgeDialog::accept()
  2. {
  3. emit userAgeChanged(newAge); // newAge is an int
  4. QDialog::accept();
  5. }

在mainwindow中:

  1. void MainWindow::showUserAgeDialog()
  2. {
  3. UserAgeDialog *dialog = new UserAgeDialog(this);
  4. connect(dialog, &UserAgeDialog::userAgeChanged, this, &MainWindow::setUserAge);
  5. dialog->show();
  6. }
  7. void MainWindow::setUserAge(int age)
  8. {
  9. userAge = age;
  10. }

三、标准对话框

标准对话框就是Qt内置的对话框,它们都是继承与QDialog类。打开帮助文档找到QDialog类,

698531-20170407183748050-975266406.png

可以看到当前版本Qt所支持的内置对话框。

  • QColorDialog:选择颜色
  • QErrorMessage:错误提示
  • QFileDialog:选择文件
  • QFontDialog:选择字体
  • QinputDialog:允许用户输入一个值,并返回该值
  • QMessageBox:模态对话框,用于提示信息,询问问题等
  • QProgressDialog:显示操作过程

下面以QMessageBox为例,做个简单介绍,QMessageBox用于显示信息提示,我们通常会用到以下几个静态函数:

  • void about(QWidget * parent, const QString & title, const QString & text):显示关于对话框。这是一个最简单的对话框,其标题是 title,内容是 text,父窗口是 parent。对话框只有一个 OK 按钮。
  • void aboutQt(QWidget * parent, const QString & title = QString()):显示关于 Qt 对话框。该对话框用于显示有关 Qt 的信息。
  • StandardButton critical(QWidget * parent, const QString & title, const QString & text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton):显示严重错误对话框。这个对话框将显示一个红色的错误符号。我们可以通过 buttons 参数指明其显示的按钮。默认情况下只有一个 Ok 按钮,我们可以使用StandardButtons类型指定多种按钮。
  • StandardButton information(QWidget * parent, const QString & title, const QString & text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton)QMessageBox::information()函数与QMessageBox::critical()类似,不同之处在于这个对话框提供一个普通信息图标。
  • StandardButton question(QWidget * parent, const QString & title, const QString & text, StandardButtons buttons = StandardButtons( Yes | No ), StandardButton defaultButton = NoButton)QMessageBox::question()函数与QMessageBox::critical()类似,不同之处在于这个对话框提供一个问号图标,并且其显示的按钮是“是”和“否”两个。
  • StandardButton warning(QWidget * parent, const QString & title, const QString & text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton)QMessageBox::warning()函数与QMessageBox::critical()类似,不同之处在于这个对话框提供一个黄色叹号图标。

我们通过以下示例来了解一下QMessageBox的简单使用:

  1. if (QMessageBox::Yes == QMessageBox::question(this,"question","are you ok?",QMessageBox::Yes|QMessageBox::No,QMessageBox::Yes))
  2. {
  3. QMessageBox::information(this,"information","I'm glad to hear that");
  4. }
  5. else {
  6. QMessageBox::information(this,"information","i'm sorry");
  7. }

我们首先使用question来询问一个问题,然后根据用户点击的按钮不同作出相应的反应。QMessageBox类的static函数使用起来非常简单方便,如果我们需要进行定制QMessageBox,则可以通过设置其属性来实现。例如做一个询问是否需要保存的对话框:

  1. //首先创建一个QMessagBox
  2. QMessageBox box;
  3. //设置对话框标题
  4. box.setText("The document has been modified");
  5. //设置对话框信息
  6. box.setInformativeText("Do you want to save your changes?");
  7. //设置详细信息,设置此属性,对话框会有一个show details的按钮,当点击该按钮时,显示详细信息
  8. box.setDetailedText("this is detail information");
  9. //设置对话框按钮
  10. box.setStandardButtons(QMessageBox::Save|QMessageBox::Discard|QMessageBox::Cancel);
  11. //设置对话框默认按钮
  12. box.setDefaultButton(QMessageBox::Save);
  13. //显示对话框并接受返回值
  14. int ret = box.exec();
  15. //根据返回值不同,作出相应的操作
  16. switch (ret) {
  17. case QMessageBox::Save:
  18. qDebug() << "save";
  19. break;
  20. case QMessageBox::Discard:
  21. qDebug() << "discard";
  22. break;
  23. case QMessageBox::Cancel:
  24. qDebug() << "cancel";
  25. break;
  26. default:
  27. break;
  28. }

运行结果如下:

698531-20170409202758660-1467543122.png

我这是在Mac下,如果是在windows下,那么Qt会自动将其设置为适应windows习惯的对话框。

转载于:https://www.cnblogs.com/wangcb/p/6675856.html

发表评论

表情:
评论列表 (有 0 条评论,508人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Qt 对话框

    1.Qt 中使用 QDialog类实现对话框。就像主窗口一样,我们通常会设计一个类继承 QDialog。QDialog(及其子类,以及所有 Qt::Dialog 类型的类)的对

    相关 Qt 标准对话框

    1.对话框种类 为应用程序设计提供了一些常用的标准对话框,如打开文件对话框、选择颜色对话框、信息提示和确认选择对话框、标准输入对话框等,用户无需再自己设计这些常用的对话框