【Qt筆記】對話框數據傳遞

對話框的出現用於完成一個簡單的或者是短時間的任務。對話框與主窗口之間的數據交互至關重要。本節將講解如何在對話框和主窗口之間進行數據交互。按照前文的講解,對話框分爲模態和非模態兩種。咱們也將以這兩種爲例,分別進行闡述。函數

 

模態對話框使用了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

相關文章
相關標籤/搜索