Qt 对话框窗体关闭时,如何自动销毁窗体类对象、清空内存

一、问题:

在主窗口点击弹出一个对话框后,对话框中包含了一个定时器。在关闭对话框后定时器对象仍在运行。

mainwindow.cpp

1 void MainWindow::on_actionKSE5K_triggered()//add actionKSE5K
2 {
3     m_jokey_ksg = new JokeyDialog(this);
4    // m_jokey_ksg->setModal(true);
5     m_jokey_ksg->show();
6 }

jokeydialog.cpp

 1 JokeyDialog::JokeyDialog(QWidget *parent) :
 2     QDialog(parent),
 3     ui(new Ui::JokeyDialog)
 4 {
 5     ui->setupUi(this);
 6  
 7     m_RTdata_flash_timer = new QTimer(this);
 8     connect(m_RTdata_flash_timer,SIGNAL(timeout()),this,SLOT(handleRTDATA_flashTimeout()));
 9     m_RTdata_flash_timer->start(RTDATA_FLASH_TIME);
10  
11 }
12  
13 JokeyDialog::~JokeyDialog()
14 {
15     delete m_RTdata_flash_timer; //no use
16     delete ui;
17 }

二、解决方法

this->setAttribute(Qt::WA_DeleteOnClose,true); // false 则不立即清空
 1 JokeyDialog::JokeyDialog(QWidget *parent) :
 2     QDialog(parent),
 3     ui(new Ui::JokeyDialog)
 4 {
 5     ui->setupUi(this);
 6     this->setAttribute(Qt::WA_DeleteOnClose,true);
 7     m_RTdata_flash_timer = new QTimer(this);
 8     connect(m_RTdata_flash_timer,SIGNAL(timeout()),this,SLOT(handleRTDATA_flashTimeout()));
 9     m_RTdata_flash_timer->start(RTDATA_FLASH_TIME);
10  
11 }
12  
13 JokeyDialog::~JokeyDialog()
14 {
15     delete m_RTdata_flash_timer; //no use
16     delete ui;
17 }

三、参考内容:
关于窗口关闭的操作,在这里指出常用的三个槽,即quit(),exit()以及close()。
首先说明窗口退出时,系统提示对话框的代码编辑。对主程序的退出,可以调用成员函数exit(),同时也可以调用槽quit(),二者此时都能起到关闭应用程序的作用。
只是应注意二者调用的方式不同。如下程序示例:

1 {
2  QApplication* app;
3  app->exit(0);
4 }
5 或者:
6 {
7  QApplication* app;
8  app->quit();
9 }

注意 通过设置

QWidget::setAttribute(Qt::WA_DeleteOnClose)

,在关闭对话框(手动close获取esc closeEvent)的时候会自动调用析构函数

此时二者是等价的,即void QApplication::quit ()等价于函数调用 QApplication::exit( 0 )。
此时,若需要给出用户提示,则只需要在程序当中添加QMessageBox的消息判断语句,以提示用户是否确定退出应用程序。
另外,quit()作为槽,也可以连接信号和槽的形式,响应某个信号后关闭应用程序。如:

QPushButton *quitButton = new QPushButton( "Quit" );
connect( quitButton, SIGNAL(clicked()), qApp, SLOT(quit()) );

如果关闭的不是应用程序,而是关闭窗口等部件的形式,则必须调用close()函数,已关闭部件。如下:

if (!(QMessageBox::information(this,tr("CT Control View"),tr("Do you really want to log out CT Control View?"),tr("Yes"),tr("No"))))
{
 this->close();
}

其中通过一条if语句,判断条件为一个对话框,根据用户的选择做出是否关闭该部件,this在这里代表当前窗口部件对象的地址。当用户选择“Yes”时,该窗口部件退出;反之则取消退出操作。

至此,我们已经简单了解了应用程序和窗口等部件的退出或关闭的代码编辑。然而,如果用户点击窗口右上角的X按键时,你会发现窗口仍然会在不给出任何提示的情况下直接退出了,即便你在程序当中已添加了提示的对话框语句。
那为什么此时的关闭操作没有按我们希望的那样先给出提示对话框呢?原因是此时的关闭操作并没有引起调用带有提示消息的关闭或退出语句。
当用户点击X关闭窗口时,系统会自动将这个事件告之某个特定的函数,即void QWidget::closeEvent ( QCloseEvent * e ),因此,这种情况应特别注意。
在关闭窗口前,可先定义一条消息语句,以提示用户是否确定关闭窗口。如:

 1 void mainWindow::closeEvent( QCloseEvent * event )
 2 {
 3     switch( QMessageBox::information( this, tr("CT Control View"),
 4      tr("Do you really want to log out CT Control View?"),
 5      tr("Yes"), tr("No"),0, 1 ) ) 
 6   {
 7      case 0:
 8    event->accept();
 9          break;
10      case 1:
11   default: 
12          event->ignore();
13          break; 
14   }   
15 }

编译程序后,系统会在用户响应close操作时,自动调用该语句。也许这个时候你还会问,上面的那个功能函数究竟是把它定义成槽呢,还是定义成成员函数。答案是二者都可以。
一方面槽本身就是一个特殊的成员函数,除了能与信号连接之外,其功能与函数无异。另一方面,此时不需要额外设置连接信号和槽,添加该功能函数之后,窗口一旦有了close操作,机会立即响应该。

尽管添加closeEvent( QCloseEvent * event )这一功能函数之后,窗口会在关闭时给出提示对话框。但有时候还会发生这样一种情况:在点击确认关闭后,还会再会出现一个对话框,即提示对话框会出现两次。那这又是什么原因呢?其实很简单,那是因为closeEvent( QCloseEvent * event )只会响应close的操作,出现两次对话框无疑是在自定义的关闭函数中又添加一条提示对话框语句,确认关闭后,响应close操作,这时系统又会马上调用closeEvent( QCloseEvent * event )这个函数。
因此,解决的办法是只定义一个带提示对话框的关闭函数,对不同的关闭操作都相应closeEvent( QCloseEvent * event )这个函数即可。

最后,如果想要在关闭主窗口或主程序时,所有打开的独立的子窗口都能同时被关闭。那么这个时候一般是在main.cpp文件中连接信号void QApplication::lastWindowClosed ();关于lastWindowClosed()的详细介绍,这里不作说明,需要使用时可以使用Qt Assistant查看其使用发法。如:

 1 int main( int argc, char ** argv )
 2 {
 3     QApplication a( argc, argv );
 4     ABMainWindow *mw = new ABMainWindow();
 5     mw->setCaption( "Qt Example - Addressbook" );
 6     a.setMainWidget( mw );
 7     mw->show();
 8     a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) );
 9     int result = a.exec();
10     delete mw;
11     return result;
12 }

这样,系统会在关闭主窗口部件时,同时关闭打开的其它子窗口程序。比较值得说明的是,并不是使用了a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) )这条语句后就一定能实现该功能。在此之前,必须特别注意是否设定了主窗口部件,即调用setMainWidget这一功能函数,这样,当关闭这一主窗口部件时,才会响应关闭这一时刻已打开的其它子窗口部件。

Qt 对话框窗体关闭时,如何自动销毁窗体类对象、清空内存

上一篇:[技术干货] Zabbix通过api监控k8s


下一篇:winform的listview,获取单击的某行内容