Qt对话框与窗口的关闭和隐藏(QCloseEvent、Qt::WA_DeleteOnClose属性、Qt::WA_QuitOnClose属性)
Qt对话框与窗口的关闭和隐藏(QCloseEvent、Qt::WA_DeleteOnClose属性、Qt::WA_QuitOnClose属性)
本文为原创文章,转载请注明出处,或注明转载自“黄邦勇帅(原名:黄勇)
本文出自本人原创著作《Qt5.10 GUI完全参考手册》网盘地址:
https://pan.baidu.com/s/1iqagt4SEC8PUYx6t3ku39Q
《C++语法详解》网盘地址:https://pan.baidu.com/s/1dIxLMN5b91zpJN2sZv1MNg
若对C++语法不熟悉,建议参阅本人所著《C++语法详解》一书,电子工业出版社出版,该书语法示例短小精悍,对查阅C++知识点相当方便,并对语法原理进行了透彻、深入详细的讲解,可确保读者彻底弄懂C++的原理,彻底解惑C++,使其知其然更知其所以然。此书是一本全面了解C++不可多得的案头必备图书。
1、为方便讲解,本文对以下概念作一区别
删除:是指窗口被销毁,也就是说窗口不存在了。比如窗口使用new创建的,则表示窗口被delete了,被销毁的窗口不能被再次使用,否则会发生内存错误。
隐藏:是指窗口不可见,但窗口并未被销毁,使用show()等函数,可以让该窗口再次可见。
关闭:是指窗口不可见,但窗口有可能是被删除了,也有可能是被隐藏了,这要视情况而定。
窗口被删除时,会同时删除其子对象,而隐藏则不会。
2、关闭窗口与终止程序
一个(应用)程序通常拥有多个窗口,关闭(或删除)一个窗口,并不一定会使程序终止,Qt中关闭窗口使用QWidget::close()槽函数,终止程序使用的是QCoreApplication::quit()静态槽函数或QCoreApplication::exit()静态函数
3、与关闭部件和终止程序有关的属性
注:以下属性其实是Qt::WidgetAttribute枚举的成员,可使用QWidget::setAttribute()函数进行设置和清除。
①、Qt::WA_DeleteOnClose属性:表示当部件接受到QCloseEvent事件时,是否让Qt删除部件。若该属性为true,则删除部件,否则部件只是隐藏。注意:设置了该属性的部件需要使用new创建,否则会产生内存错误。
②、Qt::WA_QuitOnClose属性:表示当拥有该属性的最后一个部件接受到QCloseEvent事件时,让Qt终止应用程序。默认情况下,所有Qt::Window类型的部件都具有该属性。
4、QWidget类中与关闭窗口有关的函数如下:
①、bool QWidget::close(); //槽
关闭(即删除或隐藏)部件,若部件关闭成功,则返回true,否则返回false。②、virtual void QWidget::closeEvent(QCloseEvent* e); //虚拟的,受保护的
这是QCloseEvent事件的处理函数,默认情况下,该函数接受QCloseEvent事件。该函数通常被重新实现,以确定用户是否需要关闭窗口。
5、下面为用于终止程序的函数原型
①、static void QCoreApplication::quit(); //静态的,槽
退出程序,并返回代码0(成功),此函数与调用QCoreApplication::exit(0)等同。该槽函数通常与信号连接使用,比如QPushButton *p = new QPushButton("quit"); QObject::connect( p ,& QPushButton::clicked, &app, &QCoreApplication::quit);②、static void QCoreApplication::exit( int returnCode = 0); //静态的
使用returnCode退出程序,通常returnCode为0,表示成功,任何非零值都表示错误。该函数会使程序离开主事件循环,并返回到调用QCoreApplication::exec()处,exec()函数会返回returnCode的值,若事件循环未运行,则该函数什么都不做。
6、close()函数的执行过程如下:
①、首先,向该部件发送QCloseEvent事件(不管部件是否可见)
②、然后判断部件是否接受QCloseEvent事件
若部件接受该事件(默认值),则继续下一步操作。
若部件忽略该事件,则取消关闭操作,结束后续的操作。其中最重要的是,不会对Qt::WA_DeleteOnClose属性进行判断,此时该属性不起作用。
③、接着判断部件是否被隐藏了,若未被隐藏,则隐藏,若已被隐藏,则什么也不做。然后继续下一步。
④、再接着判断部件的Qt::_WA_QuitOnClose属性,当具有Qt::WA_QuitOnClose属性的最后一个可见主窗口(即没有父窗口的窗口)被关闭时,会发送QApplication::lastWindowClosed()信号。
⑤、最后判断部件的Qt::WA_DeleteOnClose属性,若该属性为true,则删除该部件,否则什么也不做。至此整个过程结束。
⑥、总结:从以上过程可见,若部件接受QCloseEvent事件,且设置了Qt::WA_DeleteOnClose属性,则会删除该部件,若未设置该属性则只会隐藏该部件。若部件忽略QCloseEvent事件,则直接取消对该部件的关闭操作,该部件既不会被隐藏也不会被删除。由此可见对QCloseEvent事件接受还是忽略决定着对窗口关闭的处理方式,同时对该事件的处理方式与其他事件也是不同的,QCloseEvent::ignore()表示取消关闭操作(也就是说QCloseEvent事件不会被传递给父对象),而QCloseEvent::accept()则表示让Qt继续关闭操作。
7、QCloseEvent事件的发送时机如下:
从窗口菜单选择“关闭”,单击标题栏上的X按钮,调用QWidget::close()函数时。
8、可使用以下方式终止程序
直接调用quit()或exit()函数
最后一个具有Qt::WA_QuitOnClose属性的主窗口关闭时,终止程序,若没有这样的主窗口,即使所有的窗口都关闭了程序也不会结束。
9、对话框的关闭过程
对话框的reject()、accept()、done()函数,与QWidget::close()函数相同,唯一的区别是对话框不会发送QCloseEvent事件,因此不能通过QCloseEvent事件来阻止对话框的关闭。注意:此规则仅限于上述3个函数,比如点击对话框窗口的X按钮或右击标题栏选择“关闭”时,仍会发送QCloseEvent事件。若用户在对话框中按下Esc键,会调用QDialog::reject()。为了修改对话框的关闭行为,可以重新实现accept()、reject()或done()函数。
10、删除QObject对象时,会发送destroyed()信号,该信号原型如下:
void QObject::destroyed(QObject* obj = Q_NULLPTR); //信号。
当对象obj被销毁之前发送,且不能被阻止,发送该信号后,对象obj的孩子都会被立即销毁。该信号需配合Qt::WA_DeleteOnClose属性使用,当Qt::WA_DeleteOnClose属性为true的对象被删除时,会发送该信号。直接终止程序的运行,是不会发送该信号的。
示例6.6:关闭一个窗口就结束程序(理解Qt::WA_QuitOnClose属性)
#include<QtWidgets>
int main(int argc, char *argv[]){ QApplication aa(argc,argv);
QWidget w,w1; QDialog pd; QDialog pd1; QDialog pd2;QPushButton *pb=new QPushButton("AAA",&w); w.setWindowTitle("w"); w1.setWindowTitle("w1");
//除窗口w1外,窗口w和对话框的Qt::WA_QuitOnCLose属性都设置为0。w.setAttribute(Qt::WA_QuitOnClose,0); pd.setAttribute(Qt::WA_QuitOnClose,0);pd1.setAttribute(Qt::WA_QuitOnClose,0); pd2.setAttribute(Qt::WA_QuitOnClose,0);QObject::connect(pb,&QPushButton::clicked,&pd,&QDialog::show);//点击按钮pb,弹出3个对话框。QObject::connect(pb,&QPushButton::clicked,&pd1,&QDialog::show);QObject::connect(pb,&QPushButton::clicked,&pd2,&QDialog::show);w.resize(300,200); w.show(); w1.resize(300,200); w1.show(); return aa.exec();}
运行结果及说明见图6-8
示例6.7:理解Qt::WA_DeleteOnClose属性和destroyed信号
//m.h文件的内容
#ifndef M_H
#define M_H
#include<QtWidgets>
#include<QDebug>
class A:public QObject{Q_OBJECT
public slots: void f(QObject *p){ qDebug()<<"del="<<p->objectName();} };//输出被删除对象的名称
#endif // M_H//m.cpp文件的内容
#include "m.h"
int main(int argc, char *argv[]){ QApplication aa(argc,argv);QWidget w; QDialog pd; QDialog *pd1=new QDialog; QDialog *pd2=new QDialog;QPushButton *pb=new QPushButton("show",&w);QPushButton *pb1=new QPushButton("quit",&w); pb1->move(77,0);
w.setWindowTitle("w"); pd.setWindowTitle("pd"); //设置窗口标题
pd1->setWindowTitle("pd1"); pd2->setWindowTitle("pd2");
//设置Qt::WA_DeleteOnClose属性pd.setAttribute(Qt::WA_DeleteOnClose,1); pd1->setAttribute(Qt::WA_DeleteOnClose,1);
w.setObjectName("W"); pd.setObjectName("pd"); //设置对象名pd1->setObjectName("pd1"); pd2->setObjectName("pd2");
A ma;QObject::connect(pb,&QPushButton::clicked,&pd,&QDialog::show);//单击按钮pb弹出3个对话框QObject::connect(pb,&QPushButton::clicked,pd1,&QDialog::show);
QObject::connect(pb,&QPushButton::clicked,pd2,&QDialog::show);
//单击按钮pb1直接终止程序
QObject::connect(pb1,&QPushButton::clicked,&aa,&QApplication::quit);
QObject::connect(&pd,&QDialog::destroyed,&ma,&A::f);//把destroyed信号连接到槽f
QObject::connect(pd1,&QDialog::destroyed,&ma,&A::f);QObject::connect(pd2,&QDialog::destroyed,&ma,&A::f);
w.resize(300,200); w.show(); return aa.exec(); }
运行结果见图6-9,测试步骤如下
1)、点击show弹出对话框之后,若关闭pd(点击右上角的X按钮),则程序可能会崩溃(因为pd未使用new创建),关闭pd1则会销毁pd1,程序此时输出"del=pd1",关闭pd2,则只会隐藏pd2,因为各窗口之间不存在父子关系,因此本例需点击quit才能正常结束程序(因为最终在关闭窗口pd时,可能会崩溃)。
2)、重新运行程序,点击show按钮,然后关闭pd1和pd2(注意,不要关闭pd),然后再次点击show按钮,对话框pd2会被再次显示,但pd1未被显示(因为被销毁了)。
3)、再次重新运行程序,点击show,弹出3个对话框,然后点击quit直接退出程序,程序无任何输出,可见,信号destroyed未被发射。
示例6.8:关闭窗口时询问用户(QCloseEvent事件的应用)
#ifndef M_H
#define M_H
#include<QtWidgets>
class B:public QWidget{ Q_OBJECT
public: QDialog *pd1; QPushButton *pb,*pb1,*pb2,*pb3;B(QWidget* p=0):QWidget(p){pd1=new QDialog(this); pd1->setWindowTitle("PD1"); pd1->resize(222,111);pb=new QPushButton("close",this); pb1=new QPushButton("exit",this); pb1->move(88,0);pb2=new QPushButton("Yes",pd1); pb3=new QPushButton("No",pd1); pb3->move(88,0);connect(pb,&QPushButton::clicked,this,&B::f);connect(pb1,&QPushButton::clicked,this,&B::f1);connect(pb2,&QPushButton::clicked,pd1,&QDialog::accept);connect(pb3,&QPushButton::clicked,pd1,&QDialog::reject); }
void f(){ close(); } //调用close()函数关闭窗口,该函数会发送QCloseEvent事件。
void f1(){ QApplication::quit();} //注意:quit()函数不会产生QCloseEvent事件。
void closeEvent(QCloseEvent* e){ //重新实现closeEvent函数,以处理QCloseEvent事件int i = pd1->exec(); //弹出对话框pd1
//根据用户在对话框中选择的按钮,决定怎样关闭窗口if(i==1)e->accept(); //接受QCloseEvent事件,继续关闭窗口。if(i==0)e->ignore(); }}; //忽略QCloseEvent事件,阻止关闭窗口。
#endif // M_H//m.cpp文件的内容
#include "m.h"
int main(int argc, char *argv[]){ QApplication aa(argc,argv);B w; w.resize(300,200); w.show(); return aa.exec(); }
运行结果(见图6-10)及说明
当用户点击窗口qt右上角的X按钮或点击close按
钮时,会弹出对话框PD1,以确定用户是否需要关闭窗
口,当用户点击PD1中的Yes按钮时,会关闭窗口qt,
若点点No按钮,则qt不会被关闭。若用户直接点击qt
中的exit按钮,则程序直接终止,不会弹出对话框。
示例6.9:对话框与QCloseEvent事件
//m.h文件的内容
#ifndef M_H
#define M_H
#include<QtWidgets>
#include <iostream>
using namespace std;
class D:public QDialog{ Q_OBJECT
public: D(QWidget* p=0):QDialog(p){ }void closeEvent(QCloseEvent* e){ cout<<"D"<<endl; setResult(2); } };
class B:public QWidget{ Q_OBJECT
public: D *pd1; QPushButton *pb,*pb1,*pb2,*pb3,*pb4,*pb5;B(QWidget* p=0):QWidget(p){pd1=new D(this); pd1->setWindowTitle("PD1"); pd1->resize(222,111);
pb=new QPushButton("exec",this); pb1=new QPushButton("show",this); pb1->move(88,0);pb2=new QPushButton("Yes",pd1); pb3=new QPushButton("No",pd1); pb3->move(88,0);pb4=new QPushButton("result",pd1); pb4->move(0,33);connect(pb,&QPushButton::clicked,this,&B::f);connect(pb1,&QPushButton::clicked,this,&B::f1);connect(pb2,&QPushButton::clicked,pd1,&QDialog::accept);connect(pb3,&QPushButton::clicked,pd1,&QDialog::reject);connect(pb4,&QPushButton::clicked,this,&B::f2); }
void f(){ int i=pd1->exec(); cout<<"exec="<<i<<endl; }
void f1(){ pd1->show(); cout<<"show="<<pd1->result()<<endl; }
void f2(){ cout<<"result="<<pd1->result()<<endl; } };
#endif // M_H//m.cpp文件的内容
#include "m.h"
int main(int argc, char *argv[]){ QApplication aa(argc,argv);B w; w.resize(300,200); w.show(); return aa.exec();}
运行结果(见图6-11)及说明
1)、验证QCloseEvent事件未触发:点击exec以使用exec()函数显示对话框PD1,点击Yes按钮,程序输出exec=1,可见QDialog::accept()槽函数未触发QCloseEvent事件。
2)、验证exec()函数重置结果代码为0:再次点击exec按钮,显示对话框PD1,然后点击result按钮,程序输出result=0,可见exec()函数把对话框的结果代码重置为0了。
3)、验证QCloseEvent事件被触发:然后点击PD1右上角的X关闭对话框,此时程序输出D,可见此时触发了QCloseEvent事件,此时PD1的结果代码为2。
4)、验证show()不会重置结果代码为0:然后点击show按钮,以使用show()函数显示对话框PD1,此时输出show=2(注意show()函数调用后会立即反回); 然后点击result,输出result=2;可见PD1的结果代码此时为2。然后点击yes按钮关闭对话框,再点击show按钮显示对话框,此时输出show=1;然后点击result,输出result=1;可见show()函数未把结果代码重置为0。
本文作者:黄邦勇帅(原名:黄勇)
Qt对话框与窗口的关闭和隐藏(QCloseEvent、Qt::WA_DeleteOnClose属性、Qt::WA_QuitOnClose属性)相关推荐
- js弹出页面窗口和关闭
原文地址为: js弹出页面窗口和关闭 JS定时自动关闭窗口 <script language="javascript"> <!-- function clo ...
- Qt: 窗口的显示和隐藏
Qt: 窗口的显示和隐藏 隐藏窗口 1. hide() 2. setVisible(false) 3. lower() 4. close() 5. hideEvent() 显示窗口 1. show() ...
- qt 对话框关闭以及自动释放内存
关于窗口关闭的操作,在这里指出常用的三个槽,即quit(),exit()以及close(). 首先说明窗口退出时,系统提示对话框的代码编辑.对主程序的退出,可以调用成员函数exit(),同时也可以调用 ...
- Qt的对话框与窗口--Qt中主要的窗体类及其用途
Qt中主要的窗体类及其用途 常用的窗体基类是QWidget.QDialog和QMainWindow,在创建GUI应用程序时选择窗体基类就是从这3个类中选择.QWidget直接继承于QObjec ...
- Qt的对话框与窗口--标准的对话框
Qt的对话框与窗口--标准的对话框 标准的对话框 QFileDialog对话框 1.选择打开一个文件 2.选择打开多个文件 3.选择已有目录 4.选择保存文件名 QColorDialog对话框 QFo ...
- QT怎么设置字体轮廓、字体位置、字体样式、字体间距、窗口背景色大小、隐藏鼠标图标
QT怎么设置字体轮廓.字体位置.字体样式.字体间距.窗口背景色大小.隐藏鼠标图标 原创 2017年12月14日 19:05:21 标签: qt / ui 277 在qt中经常会对字体设置一些属性字体轮 ...
- 【技术】Qt对话框讲解
前言 Qt中对话框QDialog是几乎每个项目都会用到的GUI窗口对象.本文通过讲解QDialog及其子类在项目中经常被用到的功能点,帮助小伙伴们理解和掌握其使用方法. QDialog QDialog ...
- Qt对话框的事件循环分析(子线程中不能创建UI窗体分析)
重要: GUI线程和辅助线程 如前所述,每个程序在启动时都有一个线程.这个线程被称为"主线程"(在Qt应用程序中也称为"GUI线程").Qt GUI必须在这个线 ...
- Qt对话框的事件循环分析(子线程中不能创建UI窗体分析2)
Qt事件机制 QT-UI 后端 重要: GUI线程和辅助线程 如前所述,每个程序在启动时都有一个线程.这个线程被称为"主线程"(在Qt应用程序中也称为"GUI线程&quo ...
- Hello Qt(十九)——QT对话框
一.对话框简介 对话框是与用户进行简短交互的顶层窗口 QDialog是QT中所有对话框窗口的基类,QDialog继承于QWidget,是一种容器型的组件,是定制了窗口样式的特殊QWidget. QDi ...
最新文章
- 面向对象编程概念_如何向6岁的孩子解释面向对象的编程概念
- 学习junit和hamcrest的使用
- Linux-PAM PAM-MySQL的总结
- 【毕业求职季】-听说你想去大厂看学妹,带你看看腾讯微信产品岗面经(已offer)
- 1008 Elevator (20 分)【难度: 简单 / 知识点: 模拟】
- boost::io::quoted用法的测试程序
- go路由httprouter中的压缩字典树算法图解及c++实现
- 把块存放在页高速缓存中
- 孔浩老师的java视频
- 网页传奇服务器端,拍拍科技武易传奇神鸟归来商业版+网站
- iOS 下载和播放 M3U8
- 单词首字母大写 (5分)
- 慎用!wordpress的额外css功能会浪费id资源!
- Redis之EXPIRE
- 康奈尔大学计算机科学人工智能,康奈尔大学计算机科学系
- 华硕ROG冰刃5和枪神5有什么区别 哪个好
- 利用SOP激活沉默用户
- MFC自用小工具源码
- 云原生(二十七) | Kubernetes篇之自建高可用k8s集群前置概念与操作
- 实名报名超5000人!RTE2022即将开幕,声网发布RTE行业首本专业书《实时万象》
热门文章
- 分享ASP.NET视频系列教程——第十九讲 ASP.NET内置的AJAX
- “开会” 引发的思考
- word文档怎么到下一页去写_word文档怎么插入下一页
- 拟物化设计与扁平化设计
- linux中,ls -l命令显示的total的含义。
- wps-doc文件输出为pdf文件时目录报错“错误!未定义书签”解决方法
- 图像颜色与强度分离(intensity and color decouple)方法 matlab代码
- acs代表什么_思科的ACS是什么?
- Python dataframe绘制饼图_Python可视化29|matplotlib-饼图(pie)
- matlab输出相反数,在MATLAB将等于某一数列相反数的数据都赋值为0