對話框的出現用於完成一個簡單的或者是短時間的任務。對話框與主窗口之間的數據交互至關重要。本節將講解如何在對話框和主窗口之間進行數據交互。按照前文的講解,對話框分爲模態和非模態兩種。咱們也將以這兩種爲例,分別進行闡述。函數
模態對話框使用了exec()
函數將其顯示出來。exec()
函數的真正含義是開啓一個新的事件循環(咱們會在後面的章節中詳細介紹有關事件的概念)。所謂事件循環,能夠理解成一個無限循環。Qt 在開啓了事件循環以後,系統發出的各類事件纔可以被程序監聽到。這個事件循環至關於一種輪詢的做用。既然是無限循環,固然在開啓了事件循環的地方,代碼就會被阻塞,後面的語句也就不會被執行到。所以,對於使用了exec()
顯示的模態對話框,咱們能夠在exec()
函數以後直接從對話框的對象獲取到數據值。this
看一下下面的代碼:線程
void MainWindow::open() { QDialog dialog(this); dialog.setWindowTitle(tr("Hello, dialog!")); dialog.exec(); qDebug() << dialog.result(); }
上面的代碼中,咱們使用exec()
顯示一個模態對話框。最後一行代碼,qDebug()
相似於std::cout
或者 Java 的System.out.println();
語句,將後面的信息輸出到標準輸出,通常就是控制檯。使用qDebug()
須要引入頭文件。在exec()
函數以後,咱們直接能夠獲取到 dialog 的數據值。注意,exec()
開始了一個事件循環,代碼被阻塞到這裏。因爲exec()
函數沒有返回,所以下面的result()
函數也就不會被執行。直到對話框關閉,exec()
函數返回,此時,咱們就能夠取得對話框的數據。指針
須要注意的一點是,若是咱們設置 dialog 的屬性爲WA_DeleteOnClose
,那麼當對話框關閉時,對象被銷燬,咱們就不能使用這種辦法獲取數據了。在這種狀況下,咱們能夠考慮使用 parent 指針的方式構建對話框,避免設置WA_DeleteOnClose
屬性;或者是利用另外的方式。code
實際上,QDialog::exec()
是有返回值的,其返回值是QDialog::Accepted
或者QDialog::Rejected
。通常咱們會使用相似下面的代碼:對象
QDialog dialog(this); if (dialog.exec() == QDialog::Accepted) { // do something } else { // do something else }
來判斷對話框的返回值,也就是用戶是點擊了「肯定」仍是「取消」。更多細節請參考QDialog
文檔。事件
模態對話框相對簡單,若是是非模態對話框,QDialog::show()
函數會當即返回,若是咱們也這麼寫,就不可能取得用戶輸入的數據。由於show()
函數不會阻塞主線程,show()
當即返回,用戶尚未來得及輸入,就要執行後面的代碼,固然是不會有正確結果的。那麼咱們就應該換一種思路獲取數據,那就是使用信號槽機制。文檔
因爲非模態對話框在關閉時能夠調用QDialog::accept()
或者QDialog::reject()
或者更通用的QDialog::done()
函數,因此咱們能夠在這裏發出信號。另外,若是找不到合適的信號發出點,咱們能夠重寫QDialog::closeEvent()
函數,在這裏發出信號。在須要接收數據的窗口(這裏是主窗口)鏈接到這個信號便可。相似的代碼片斷以下所示:it
//!!! Qt 5 // in dialog: void UserAgeDialog::accept() { emit userAgeChanged(newAge); // newAge is an int QDialog::accept(); } // in main window: void MainWindow::showUserAgeDialog() { UserAgeDialog *dialog = new UserAgeDialog(this); connect(dialog, &UserAgeDialog::userAgeChanged, this, &MainWindow::setUserAge); dialog->show(); } // ... void MainWindow::setUserAge(int age) { userAge = age; }
不要擔憂若是對話框關閉,是否是還能獲取到數據。由於 Qt 信號槽的機制保證,在槽函數在調用的時候,咱們始終可使用sender()
函數獲取到 signal 的發出者。關於sender()
函數,能夠在文檔中找到更多的介紹。順便說一句,sender()
函數的存在使咱們能夠利用這個函數,來實現一個只能打開一個的非模態對話框(方法就是在對話框打開時在一個對話框映射表中記錄下標記,在對話框關閉時利用sender()
函數判斷是否是該對話框,而後從映射表中將其刪除)。class