讓你的 Qt 桌面程序看上去更加 native(五):QDialog

雖然 Nokia 剛剛宣佈和微軟合作,推出 WP7 的智能手機,現在 IT 界依然一片譁然(不過也是在意料之中),但這並不會影響我們對於 Qt 的興趣。好了,現在我們來看的是關於 QDialog 的一些東西。

首先先來看 QDialog 的一副截圖(出自 Qt Developer Day, 2009):

在這裏,我們要注意的是不同平臺之上對話框的按鈕的不同。其實這是同一段代碼編譯的,沒有使用條件編譯技術。那麼是如何做到的呢?答案是使用 QDialogButtonBox 這個類。

QDialogButtonBox 用於管理對話框按鈕的順序、佈局、文本和圖標等,以保證這些在不同平臺能夠具有不同表現。如果我們沒有 Mac 系統,我們怎麼知道該如何佈局按鈕呢?我們怎麼獲得這些按鈕在不同平臺上的圖標呢?這些都不會成爲我們實現程序的障礙,因爲使用 QDialogButtonBox 就足夠了。例如,要實現上面的效果,我們只需要一行代碼:

  1. QDialogButtonBox box(QDialogButtonBox::Save |   
  2.                       QDalogButtonBox::Discard |  
  3.                       QDialogButtonBox::Cancel);  

這樣,Qt 就會在不同的平臺做出不同的表現。

QDialogButtonBox 爲不同的按鈕分配不同的角色來實現這一功能。因此,我們在上面的 QDialogButtonBox::Save 這些實際都是一個簡單的 enum,用於標記按鈕的角色。如果你需要使用自己的按鈕,並且爲之附加角色,那麼可以使用下面的代碼:

  1. QDialogButtonBox box;  
  2. box.addButton(myButton, QDialogButtonBox::AcceptRole); 

這樣,myButton 的角色就是 QDialogButtonBox::AcceptRole,而 QDialogButtonBox 也能夠根據這個角色爲之分配合適的圖標和位置等等。

QDialogButtonBox 先告一段落,下面來說說模態對話框。什麼是模態對話框?所謂模態,就是在對話框彈出來之後,能夠阻塞後面的窗口。Windows 上一般在退出時會彈出來一個問你是否保存的對話框,就是一個模態對話框。當它出現的時候,後面的窗口是不能點擊的,必須要你關閉這個對話框之後纔可以。在 Qt 實現模態對話框很簡單:

  1. MyQDialogSubclass dialog;   
  2. // Various bits of initialization   
  3. if (dialog.exec() == QDialog::Accept)  {  // HERE!!! 
  4.  // Set new values or do extra work       
  5.  // based on results.   

這段代碼在運行時,會在標記 HERE 註釋這行阻塞,具體是 QDialog::exec() 這個函數。這之後的代碼在你關閉 dialog 對話框之後纔會被執行。利用這一技術,你就可以在 if 裏面獲取依賴於對話框返回值的數據。例如,對話框用於收集用戶數據等。

  1. class MyDialog : public QDialog 
  2. public
  3.     QString name; 
  4. }; 
  5. // .... 
  6. MyDialog d; 
  7. if(d.exec() == QDialog::Accept) { 
  8.     QString name = d.name; 
  9.     // do something with name... 

上面的代碼,MyDialog 用於用戶輸入 name 的值。我們使用模態對話框,就可以在 if 裏面獲取這個值了。

不過,不同平臺上的模態對話框的使用方式是不一樣的。比如,Windows 平臺上,模態對話框用於嚴重錯誤的提示,或者是在繼續之前必須完成的任務;KDE 上,模態對話框用於可能造成數據丟失或者嚴重後果的交互。

Qt 中,對話框的打開具有三種方式:

  • QDialog::show(): 非模態
  • QDialog::exec(): 模態
  • QDialog::open(): 窗口模態

前兩種我們很容易理解,下面來看看什麼是窗口模態。比如,我們有兩個窗口(以下圖示來自 Qt Developer Day, 2009):

使用如下代碼,我們用 open() 函數打開一個對話框:

  1. if(!messageBox) { 
  2.     messageBox = new QMessageBox("SDI"
  3.                                  "The document has been modified. \n" 
  4.                                  "Do you want to save your changes?"
  5.                                  QMessageBox::Warning, 
  6.                                  QMessageBox::Yes | QMessageBox::Default, 
  7.                                  QMessageBox::No, 
  8.                                  QMessageBox::Cancel | QMessageBox::Escape, 
  9.                                  this); 
  10.     connect(messageBox, SIGNAL(finished(int)), SLOT(handleDialogClose(int))); 
  11. messageBox->open(); 

看看運行的結果:

這就是 open() 函數的效果:它類似模態對話框,但是隻會阻塞一個窗口,而不是將整個系統阻塞掉。

最後一個要說的技術是 QFormLayout。這個佈局用於展示表單。來看一下下面的截圖(出自 Qt Developer Day, 2009):

注意這裏的文本對齊方式和按鈕的順序。前面已經說過用 QDialogButtonBox 實現不同平臺下按鈕的順序,而上面的對齊方式則是使用 QFormLayout 實現,例如:

  1. QFormLayout *layout = new QFormLayout; 
  2. layout->addRow(tr("Name:"), nameLineEdit); 
  3. // more... 

這樣,我們又能夠使用簡單的代碼實現不同平臺的不同佈局表現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章