1.説明の便宜上、この記事では次の概念を区別します
。削除:ウィンドウが破壊されている、つまりウィンドウが存在しないことを示します。たとえば、ウィンドウがnewで作成された場合、ウィンドウが削除され、破棄されたウィンドウを再度使用できないことを意味します。そうしないと、メモリエラーが発生します。
非表示:ウィンドウは非表示ですが、ウィンドウは破棄されていません。show()などの関数を使用して、ウィンドウを再度表示できます。
閉じる:ウィンドウは表示されませんが、状況に応じてウィンドウが削除または非表示になる場合があります。
ウィンドウが削除されると、その子オブジェクトも同時に削除されますが、非表示の場合は削除されません。
2.ウィンドウを
閉じてプログラムを終了する(アプリケーション)プログラムには通常複数のウィンドウがあります。ウィンドウを閉じる(または削除する)と必ずしもプログラムが終了するわけではありません。Qtでは、ウィンドウを閉じるにはQWidget :: close()が使用されます。プログラムを終了するにはslot関数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 :: require()が呼び出されます。ダイアログボックスの終了動作を変更するために、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属性と破棄されたシグナルを理解する
//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)ポップアップ表示ダイアログボックスをクリックした後、pdを閉じると(右上隅のXボタンをクリック)、プログラムがクラッシュする可能性があり(pdはnewで作成されないため)、pd1を閉じるとpd1が破壊され、プログラムは「del = pd1」を出力し、pd2を閉じます。ウィンドウ間に親子関係がないため、pd2のみが非表示になります。したがって、この例では、プログラムを正常に終了するには、終了をクリックする必要があります(クラッシュする可能性があるため)ウィンドウpdが最終的に閉じられたとき)。
2)プログラムを再実行し、[表示]ボタンをクリックして、pd1とpd2を閉じ(注意、pdを閉じないでください)、もう一度[表示]ボタンをクリックすると、ダイアログボックスpd2が再度表示されますが、pd1は表示されません。 (破壊されているため)。
3)プログラムを再実行し、[表示]をクリックし、3つのダイアログボックスが表示されたら、[終了]をクリックしてプログラムを直接終了します。プログラムには出力がなく、破棄されたシグナルが起動されていないことがわかります。
示例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(); }
ユーザーがウィンドウの右上隅qtXをクリックするか、閉じるボタンを
押すと、ダイアログボックスにPD1が表示され、ユーザーがウィンドウを閉じる必要があるかどうかを判断するための操作結果(図6-10を参照)と説明
ユーザーがPD1で[はい]をクリックすると、ウィンドウ
qtが閉じます。[いいえ]ボタンをクリックすると、qtは閉じません。ユーザー
がqtの終了ボタンを直接クリックすると、プログラムはダイアログボックスをポップアップせずに直接終了します。
示例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を表示し、[はい]ボタンをクリックすると、プログラムがexec = 1を出力し、QDialog ::が表示されます。 accept()スロット関数は、QCloseEventイベントをトリガーしません。
2).exec()関数が結果コードを0にリセットすることを確認します。execボタンをもう一度クリックしてダイアログボックスPD1を表示し、結果ボタンをクリックすると、プログラムはresult = 0を出力し、exec()関数は次のことができます。ダイアログボックスの結果コードを0にリセットしていることがわかります。
3)QCloseEventイベントがトリガーされていることを確認します。次に、PD1の右上隅にあるXをクリックしてダイアログボックスを閉じます。このとき、プログラムはDを出力します。この時点でQCloseEventイベントがトリガーされていることがわかります。このとき、PD1の結果コードは2です。
4).show()が結果コードを0にリセットしないことを確認します。次に、showボタンをクリックしてshow()関数を使用し、ダイアログボックスPD1を表示します。このとき、出力show = 2(show( )関数は呼び出しの直後に戻ります);次に結果をクリックし、結果= 2を出力します;この時点でPD1の結果コードが2であることがわかります。次に、[はい]ボタンをクリックしてダイアログボックスを閉じ、[表示]ボタンをクリックしてダイアログボックスを表示します。このとき、出力show = 1;次に結果をクリックし、出力result = 1;ショーが表示されていることがわかります。 ()関数は結果コードを0にリセットしません。