Qt 入门 3 之对话框 QDialog
本文从以下几点分开讲述:
- 对话框的基本原理介绍
- 两种不同类型的对话框
- 一个由多个窗口组成并且窗口间可以相互切换的程序
1.模态和非模态对话框
- QDialog 类是所有对话框窗口类的基类。对话框窗口是一个经常用来完成短小任务或者和用户进行简单交互的顶层窗口
- 按照运行对话框时是否还可以和该程序的其他窗口进行交互,对话框常被分为两类:模态的(model) 和非模态的(modeless)。
- 新建Qt Qwidgets应用项目,名称为mydialog1,然后项目中命名如下图,找到
mywidget.cpp文件添加一下代码:
#include "mywidget.h"
#include "ui_mywidget.h"
#include"qdialog.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui->setupUi(this);QDialog dialog(this);dialog.show();
}
- 在 MyWidget 类的构造函数中定义了一个QDialog类对象,还指定了 dialog的父窗口为 MyWidget 类对象(即this参数的作用),最后调用show()函数让其显示。运行程序时就发现,一个窗口一闪而过,然后就只显示MyWidget窗口了,为什么会这样呢?因为对于一个函数中定义的变量,等这个函数执行结束后,它就会自动释放。也就是说,这里的 dialog对象只在这个构造函数中有用,等这个构造函数执行完了,dialog也就消失了。为了不让dialog消失,可以将QDialog对象的创建代码更改如下:
QDialog* dialog = new QDialog(this);dialog->setWindowTitle(QObject::tr("dialog1"));dialog->show();
- 可以正常显示了。需要说明的是,我们说定义一个对象是指“QDialog dialog;”这样的方式,而像“QDialog *dialog;“这样不能被称为定义了一个对象,而应该说成定义了一个指向QDialog类对象的指针变量。后面也会把“QDialog *dialog;"说成是定义了一个QDialog对象。再补充一点,这里为对话框对象指明了父窗口,所以就没有必要使用delete来释放该对象了
其实不用指针也可让对话框显示出来,可以将代码修改如下:
QDialog dialog(this);dialog.exec();
- 这时运行程序就会发现对话框弹出来了,但是MyWidget(MyWidget)窗口并没有出来,当关闭对话框后,MyWidget窗口才弹出来。这个对话框与前面那个对话框的效果不同,称它为模态对话框,而前面那种对话框称为非模态对话框。
- 模态对话框就是在没有关闭它之前,不能再与同一个应用程序的其他窗口进行交互,比如新建项目时弹出的对话框。而对于非模态对话框,既可以与它交互,也可以与同一程序中的其他窗口交互,如Microsoft Word中的查找替换对话框。就像前面看到的,要想使一个对话框成为模态对话框,则只需要调用它的exec()函数;而要使其成为非模态对话框,则可以使用new操作来创建,然后使用show()函数来显示。其实使用show()函数也可以建立模态对话框,只须在其前面使用setModal()函数即可。例如:
QDialog * dialog = new QDialog(this);
dialog->setModal(true);
dialog->show();
- 运行程序后可以看到,生成的对话框是模态的。但是,它与用exec()函数时的效果是不一样的,因为现在的MyWidget窗口也显示出来了。这是因为调用完show()函数后会立即将控制权交给调用者,程序可以继续往下执行。而调用exec()数却不同,只有当对话框被关闭时才会返回。与setModal()函数相似的还有一个setWindowModality()函数,它有一个参数来设置模态对话框要阻塞的窗口类型,可以是Qt::NonModal(不阻塞任何窗口,就是非模态)、Qt::WindowModal(阻塞它的父窗口、所有祖先窗口以及它们的子窗口)或Qt::ApplicationModal(阻塞整个应用程序的所有窗口)。而setModal()函数默认设置的是Qt::ApplicationModal。
2.多窗口切换
2.1 认识信号与槽
- Qt中使用信号与槽机制来完成对象之间的协同操作
- 简单来说,信号和槽都是函数,比如单击窗口上的一个按钮后想要弹出一个对话框,那么可以将这个按钮的单击信号和自定义相关的槽关联起来,在这个槽中创建一个对话框来显示它
- 举个例子,在之前的项目中做出如下更改:
- 在mywidget.h中加入槽函数 定义:
public:void showChildDialog();
- 在mywidget.cpp中添加槽函数定义
void MyWidget::showchildDialog()
{QDialog* dialog = new QDialog(this);dialog->show();
}
- 在mywidget.cpp 基类构造函数中添加connect函数:
connect(ui->showchildButton,&OPushButton::clicked,this, &MyWidget::showchildDialog);
-
然后点击mywidget.ui做出如下界面编辑操作:新拉一个pushputton并更改按钮名和显示文本,新拉一个label并更改显示本文
-
上述更改主要想实现以下功能:点击 按钮 则显示新的子窗口
-
connect函数详解,其时QObject类中的函数,因为QWidget继承自QObject,因此可以直接使用
-
函数4个参数分别对应:发射信号的对象、发射的信号、接收信号的对象、要执行的槽
-
上述信号与槽的连接成为手动关联,还有一种是自动关联,比如前边的槽函数可以重命名为 on_showChildButton_clicked(),就是由字符on 、发射信号的部件对象名和信号名组成
2.2 自定义对话框
-
依然在前边的项目中更改:
-
第一步,添加自定义对话类框。依然在前面的项目中更改。首先向该项目中添加Qt设计师界面类。界面模板选择DialogwithoutButtons,类名改为MyDialog。然后在设计模式中向窗口添加两个PushButton,并且分别更改其显示文本为“进人主界面”和“退出程序”
-
第二步,设计信号与槽。这里使用设计器来实现”退出程序" 按钮的信号和槽的关联。单击设计器上方的Edit Signals/Slots图标,或者按下快捷键F4,于是进入了部件的信号和槽的编辑模式。在“退出程序”按钮上按住鼠标左键,然后拖动到窗口界面上,这时松开鼠标左键。在弹出的配置连接对话框中选择“显示从QWidget继承的信号和槽”选项,然后在左边的QPushButton栏中选择信号clicked(),在右边的 QDialog栏中选择对应的槽close(),完成后单击OK按钮
-
如图下图所示(这里还可以单击“编辑”按钮添加自定义的槽,不过这还需要在MyDialog类中实现该槽)。这时“退出程序”按钮的单击信号就和对话框中的关闭操作槽进行了关联。要想取消这个关联,只须在信号和槽编辑模式中选择这个关联;当它变为红色时,按下Delete键,或者右击选择“删除”。也可以在设计器下方的信号和槽编辑器中看到设置好的关联。当然,直接在信号和槽编辑器中建立关联也是可以的,它与鼠标选择部件进行关联是等效的。设置好关联后按下F3键,或者单击“编辑控件”图标,则回到部件编辑模式。
-
现在设置“进人主界面”按钮的信号和槽的关联。在该按钮上右击,在弹出的级联菜单中选择“转到槽”,然后在弹出的对话框中选择clicked()信号,并单击OK按钮。这时便会进人代码编辑模式,并且定位到自动生成的on_pushButton_clicked()槽中在其中添加代码:
void MyDialog::on_pushButton_clicked()
{accept();
}
- 这个 accept()函数是 QDialog类中的一个槽,对于一个使用exec()函数实现的模态对话框,执行了这个槽就会隐藏这个模态对话框,并返回QDialog::Accepted值,这里就是要使用这个值来判断是哪个按钮被按下了。与其对应的还有一个**reject()**槽,它可以返回一个 QDialog::Rejected值,前面的“退出程序”按钮也可以关联这个槽。
- 在主界面中使用自定义的对话框,更改 main 函数如下:
#include "mywidget.h"
#include"mydialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{QApplication a(argc, argv);MyWidget w;//w.show();//return a.exec;MyDialog dialog;if(dialog.exec()==QDialog::Accepted){w.show();return a.exec();}else{return 0 ;}
}
- 运行程序后可以发现,已经实现了从录对话框到主界面,再从主界面显示一个对话框的应用了。执行后效果如下:
1744004049407
- 再来实现可以从主界面重新进入登录界面的功能。双击mywidget.ui文件,在设计模式中再向界面添加两个PushButton,分别更改它们的显示文本为“重新登录”和“退出”。然后使用信号和槽模式将“退出”按钮的clicked()信号和MyWidget 界面的**close()槽关联。完成后再转到“重新登录”按钮的clicked()**信号的槽,并更改如下:
void MyWidget::on_pushButton _clicked()
{//先关闭界面,其实是隐藏了,并没有真正退出,然年新建MyDialog对象close();MyDialog dlg;//如果按下了[重新登录]按钮,则再次显示主界面if(dlg.exec()==QDialog::Accepted)show();
}
运行后效果如下:
1744004593360