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這一功能函數,這樣,當關閉這一主窗口部件時,才會響應關閉這一時刻已打開的其它子窗口部件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM