Bootstrap

QT6学习 第九天 QDialog

对话框 QDialog

模态和非模态对话框

QDialog 类是所有对话框类的基类。对话框是一个经常用来完成短小任务或和用户进行简单交互的顶层窗口。按照运行对话框时是否还可以和该程序的其他窗口交互,对话框被分为两类:模态的和非模态的。

新建 Qt Widgets 项目,命名 mydialog1,基类用 QWidget,类名 MyWidget。打开 cpp 文件,添加 QDialog 头文件,构造函数中添加代码:

//创建 QDialog 对象 dialog,并指定父窗口 this
QDialog dialog(this);
dialog.show();

我们运行程序会发现一个窗口一闪而过,然后就只显示 MyWidget 窗口了,因为对于一个函数中定义的变量,等这个函数执行结束后,他就会自动释放。也就是说,这里的 dialog 对象只在这个构造函数中有用,等这个构造函数执行完了,dialog 也就消失了。为了不让 dialog 消失,读者可以将 QDialog 对象的创建代码改一下。

QDialog *dialog = new QDialog(this);
dialog->show();

这里使用了 QDialog 对象的指针,并使用 new 来创建对象 dialog。这次再运行就可以正常显示了。这里因为 dialog 指明了父窗口,所以就没有必要使用 delete 释放该对象了,因为父对象销毁时会自动将其销毁。
这种方式成为非模态对话框

其实,不用指针也可以让对话框显示出来,可以不使用指针的方式创建对象。

QDialog dialog(this);
dialog.exec();

这次运行程序,发现对话框弹出来了,但是 MyWidget 窗口没出来,关闭对话框后,MyWidget 才弹出来。
这种方式成为 模态对话框

模态可以理解为会阻塞其他窗口的窗口,非模态可理解为不会阻塞任何窗口的窗口。

两者创建的不同在于,非模态通过 new 来动态开辟了内存空间,并用 show() 展示,后边通过 delete(或父窗口的delete) 来销毁。而模态是没有开辟内存空间,并且要用 exec() 让他一直运行,会随着构造函数的执行完而消失。如果想用 show() 创建模态对话框,需要在其前一行加dialog->setModal(true)

QDialog *dialog= new QDialog(this);
dialog->setModal(true);
dialog->show();

这里说一下 show() 和 exec() ,调用 show() 后会立即将控制权交给调用者,程序可以继续往下执行。而 exec() 却不同,只有当对话框被关闭时才会返回。 从我们的项目上看区别是 exec 不会显示 MyWidget 窗口,而 show 可以。

与 setModa() 相似的还有一个 setWindowModality(),它有一个参数来设置模态对话框要阻塞的窗口类型,分别有,NonModal、WindowModal、ApplicationModal三个选项。默认是:ApplicationModal

模态对话框在没关闭它之前,不能再与同一个应用程序的其他窗口进行交互,比如新建项目弹出的对话框。而对于非模态对话框,既可以与它交互,也可以与同一程序中的其他窗口交互,如一些软件中的”查找与替换“对话框。

标准对话框

Qt 提供了一些常用的对话框类型,他们全都继承自 QDialog 类,并增加了自己的功能。

这些对话框包括:
颜色对话框 QColorDialog、错误信息对话框 QErrorMessage
文件对话框 QFileDialog、字体对话框 QFontDialog
输入对话框 QInputDialog、消息对话框 QMessageBox
进度对话框 QProgressDialog、向导对话框 QWizard

来看 QColorDialog 和 QProgressDialog 的示例。

新建 Qt Widget 项目,命名 mydialog2 ,基类选QWidget,类名MyWidget。在 ui 文件中拖入两个按钮,分别修改显示文本为”颜色对话框“和”进度对话框“。

颜色对话框

颜色对话框类 QColorDialog 提供了一个可以获取指定颜色的对话框部件。我们来创建一个。

在 mywidget.cpp 中添加 QColorDialog 头文件,然后右击颜色对话框按钮选信号槽里的 clicked() ,在构造函数中添加代码:

void MyWidget::on_pushButton_clicked(){
//这里使用了QColorDialog的静态函数getColor()来获取颜色
//它的3个参数的作用分别是设置初始颜色、指定父窗口和设置对话框标题
	QColor color = QColorDialog::getColor(Qt::red,this,tr("颜色对话框"));
	qDebug() << "color:" << color;
}	

getColor() 函数返回一个 QColor 类型数据。
运行程序,然后按下“颜色对话框”按钮,如果不选择颜色,直接单击OK按钮,那么输出信息应该是QColor(ARGB 1, 1, 0, 0),这里的4个数值分别代表透明度(alpha)、红色(red)、绿色(green)和蓝色(blue)等分量。它们的数值都是0.0~1.0。对于alpha来说,1.0表示完全不透明,这是默认值,而0.0表示完全透明。对于三基色红、绿、蓝的数值,还可以使用0~255来表示。

前面使用 QColorDialog 类的静态函数来直接显示颜色对话框,这样做的好处是不用创建对象。但是如果想要更灵活地设置,则可以先创建对象,然后进行各项设置,例如:

void MyWidget::on_pushButton_clicked(){
	QColorDialog dialog(Qt::red,this);
	dialog.setQption(QColorDialog::ShowAlphaChannel);
	//模态方式运行对话框
	dialog.exec();
	QColor color = dialog.currentColor();
	qDebug() << "color:" << color;
}

进度对话框

就是一个进度条。 需添加 QProgressDialog 头文件。
右键”进度对话框“选信号槽里的 clicked() ,并添加代码。

void MyWidget::on_pushButton_2_clicked(){
	//创建 QProgressDialog 对象 dialog,参数为:标签内容,按钮显示文本,最大/最小值,父窗口
	QProgressDialog dialog(tr("文件复制进度"),tr("取消"),0,50000,this);
	dialog.setWindowTitle(tr("进度对话框"));
	//将对话框设置为模态
	dialog.setWindowModality(Qt::WindowModal);
	dialog.show();

	for(int i = 0;i < 50001;i++){
		dialog.setValue(i);
		
		//这是一个线程相关函数,防止软件在执行耗时任务时软件卡顿问题
		//等于一直在刷新界面
		QCoreApplication::processEvents();
		if(dialog.wasCanceled()){
			break;
		}
	}
	qDebug() << tr("复制结束!");

QProgressDialog 也可以实现非模态对话框,不过它需要定时器等的帮助。

;