- 模态对话框和非模态对话框
什么是模态对话框,模态对话框就是对对话框后面的背景(即主界面)进行模糊化,即模态对话框弹出的时候,不能再使用背景的任何功能,直到你将模态对话框关闭。
同理非模块对话框就是非模块对话框弹出的时候仍能对主界面进行操作。
非模态对话框:
cpp
QDialog *dialog = new QDialog(this);
dialog->resize(200, 100);
dialog->show();
模态对话框:
窗口弹出来后不能再对主界面进行操作,将主界面进行模糊化。
方法1:
cpp
dialog->exec();
使用exec()方法来显示对话框,但是这种方法有个缺点就是只会显示对话框而不会显示主界面,其原因是exec是一个堵塞函数,调用exec以后,主界面的构造函数没办法执行完,直到手动关闭该对话框。
方法2:
cpp
dialog->setModal(true);
dialog->show();
设置dialog的模式为true,即手动设置模式为模态对话框
此时可见背景白了,不关闭该对话框没办法操作主界面。
需要注意一个点,我们知道Qt中的是使用对象树来管理QObject的,在这种结构中,每个 QObject 对象都可以有一个父对象和多个子对象。当创建一个 QObject 对象并指定了它的父对象时,这个对象就会被加入到父对象所在的对象树中。使用对象树的好处主要是当父对象被析构时,其下的所有子对象也会被自动析构。
也就是说如果父对象没有调用析构函数的时候,子对象也是不会调用析构函数的,如果有一个人闲得一直创建子对象(比方说创建一个对话框,又关闭,然后又创建...),是不是就有内存泄漏的风险,因此,为了防止这种事情发生,我们可以这么做:
cpp
dialog->setAttribute(Qt::WA_DeleteClose);
我们可以设置dialog的属性(Attribute)这样就可以再关闭该对话框的时候自动调用析构函数,而不用等到父对象调用析构的时候再自动调用析构。
下面介绍标准对话框:
Qt支持8种对话框:
我们常常会忘记一些类是如何定义,其方法是怎么样的,如果想详细查看这个类的设置,可以将鼠标指向类名,然后按下F1即可进入assistant,并自动定位该类的描述。
1.颜色对话框:
cpp
#include <QColorDialog>
QColor color = QColorDialog::getColor(Qt::red, this, "颜色对话框");
//一共可以设置4个参数,我这里只设置了三个,最后一个参数是用来设置颜色对话框的外观的,这里用默认值
//第一个参数是打开后的默认颜色,第二个是指定其父对象的地址,第三个是设置颜色对话框的标题
//返回值是所选的颜色
- 文件对话框
cpp
#include <QFileDialog>
QString fileName = QFileDialog::getOpenFileName(this, "OpenFile", "D://", "图片 (*.png *.jpg)");
//返回的是打开的路径和文件名
- 字体对话框
cpp
#include <QFontDialog>
QFont font = QFontDialog::getFont(&ok, QFont("Times", 12), this);
//返回选择的字体,参数是是否有选择,第二个是如果没选的话返回的默认自己,第三个是父对象地址
- 输入对话框
cpp
#include <QInputDialog>
QString inputString = QInputDialog::getText(this, "文本对话框", "用户名:", QLineEdit::Normal, "请输入用户名", &ok);
- 消息对话框
cpp
#include <QMessageBox>
QMessageBox::information(this, "信息对话框", "请问要使用Qt吗?", QMessageBox::Ok, QMessageBox::Cancel);
QMessageBox::critical(this, "危险对话框", "请使用其他GUI。", QMessageBox::Close);
QMessageBox::about(this, "关于对话框", "这是一个关于对话框");
QMessageBox::warning(this, "警告对话框", "这是一个警告对话框", QMessageBox::Ok, QMessageBox::Cancel);
消息对话框默认是模态对话框。
- 进程对话框
QProgressDialog
是一个有一个取消按钮的对话框
cpp
#include <QProgressDialog>
QProgressDialog progressdialog("复制进度条为:", "取消", 0, 50000, this);
progressdialog.setMinimumSize(400, 300);//设置进度对话框的大小
progressdialog.setWindowTitle("进程对话框");
progressdialog.setWindowModality(Qt::WindowModal);
progressdialog.show();
for(int i = 0; i < 50000; i++)
{
progressdialog.setValue(i);
QCoreApplication::processEvents();//检查其他线程是否需要使用cpu
if(progressdialog.wasCanceled())
break;
}
progressdialog.setValue(50000);
qDebug() << "拷贝已经完成";
为什么这里创建进度对话框的时候用的是创建对象的方式来创建,而不是使用new?
防止内存泄漏,如果我使用new来创建对象的话,只有当主界面关闭的时候,才会调用进程对话框的析构函数,这意味着当主界面没有关闭的时候,我们可以创建无数个进程对话框然后再关闭,但是这个时候创建进程对话框的内存没有回收,这可能导致内存泄漏。为了避免这种事情发生,我们可以直接创建对象,这样当函数结束的时候,将会自动调用对象的析构函数,而不需要等待主界面关闭后再调用析构函数。
- 错误信息对话框
cpp
#include <QErrorMessage>
qem->setWindowTitle("错误信息对话框");
qem->showMessage("危险");
如果我们想要设置好Show this message agin,让它取消后不再显示该错误对话框,我们应该在全局设置一个QErrorMessage对象,指针放在类的声明中,在窗口的构造函数进行动态创造该对象,这样,全局就只有一个QErrorMessage对象,而不能是在PushButtion的槽下设置,如果在PushButtion的槽下创建对象,则相当于每按一次PushButton就会调用一次槽,就会生成一个新的QErrorMessage对象,这样我们取消勾选则不会生效,再按一次PushButton还是会出现错误信息对话框。
- 向导对话框
cpp
QWizardPage *createPage1()
{
//设置第一页的内容
QWizardPage *page = new QWizardPage;
page->setTitle("第一步");
return page;
}
QWizardPage *createPage2()
{
//设置第二页的内容
QWizardPage *page = new QWizardPage;
page->setTitle("第二步");//用的是setTitle而不是setWindowTitle
return page;
}
void MainWindow::on_pushButton_8_clicked()
{
QWizard wizard(this);
wizard.setWindowTitle("向导对话框");
wizard.addPage(createPage1());//在向导对话框中设置页
wizard.addPage(createPage2());
wizard.exec();
}