2月 23, 2009

【翻譯】Address Book 5 - Adding a Find Function

@
tutorials/addressbook/part5/addressbook.cpp
tutorials/addressbook/part5/addressbook.h
tutorials/addressbook/part5/finddialog.cpp
tutorials/addressbook/part5/finddialog.h
tutorials/addressbook/part5/main.cpp
tutorials/addressbook/part5/part5.pro

  在這一章,我們著眼於 Address Book 程式中找出聯絡人與住址的方法。



  當我們持續加入聯絡人到我們的 Address Book 程式中,利用 NextPrevious 按紐來進行導覽將變得令人厭煩。在這個情況下,一個 Find 函式將會更加有效率的找到聯絡人。上方的截圖顯示了 Find 按紐,以及它在按鈕面板(panel)上的位置。

  當使用者點擊 Find 按鈕時,顯示一個對話視窗(dialog)是相當有用的,它可以提示使用者輸入聯絡人的姓名。Qt 提供了 QDialog--我們在這個章節子類別化它--來實現一個 FindDialog 類別。


Defining the FindDialog Class



  為了要子類別化 QDialog,我們首先在 finddialog.h 檔案中引入 QDialog 的標頭。同樣的,由於我們將要在我們的對話視窗類別中使用 QLineEditQPushButton,所以我們使用前向宣告來宣告它們。

  正如我們的 AddressBook 類別,FindDialog 類別包含了 Q_OBJECT 巨集,且它的建構子被宣告成允許一個 QWidget 父元件,即使對話視窗將會做為一個單獨的視窗開啟。

 #include <QDialog>

 class QLineEdit;
 class QPushButton;

 class FindDialog : public QDialog
 {
     Q_OBJECT

 public:
     FindDialog(QWidget *parent = 0);
     QString getFindText();

 public slots:
     void findClicked();

 private:
     QPushButton *findButton;
     QLineEdit *lineEdit;
     QString findText;
 };

  我們定義了一個公開函式--getFindText()--供 FindDialog 實體化的類別使用,這允許它們獲得由使用者輸入的文字。一個公開的 slot--findClicked()--被定義成在使用者點擊 Find 按鈕時處理搜尋字串。

  最後,我們定義私有變數:findButtonlineEditfindText,分別對應 Find 按鈕、使用者輸入搜尋字串的單行文字框(line edit)、與一個用以儲存稍後使用的搜尋字串的內部(internal)字串。


Implementing the FindDialog Class

  在 FindDialog 的建構子中,我們設置了私有變數:findButtonlineEditfindText。我們使用一個 QHBoxLayout 以將元件放在適當位置。

 FindDialog::FindDialog(QWidget *parent)
     : QDialog(parent)
 {
     QLabel *findLabel = new QLabel(tr("Enter the name of a contact:"));
     lineEdit = new QLineEdit;

     findButton = new QPushButton(tr("&Find"));
     findText = "";

     QHBoxLayout *layout = new QHBoxLayout;
     layout->addWidget(findLabel);
     layout->addWidget(lineEdit);
     layout->addWidget(findButton);

     setLayout(layout);
     setWindowTitle(tr("Find a Contact"));
     connect(findButton, SIGNAL(clicked()), this, SLOT(findClicked()));
     connect(findButton, SIGNAL(clicked()), this, SLOT(accept()));
 }

  我們設定了佈局與視窗標題,也將 signal 連接到它們各自的 slot。注意,findButton 的 clicked() signal 被連接到了 findClicked()accept()。QDialog 提供的 accept() slot 隱藏對話視窗,並將結果代碼(result code)設為 Accepted。我們使用這個函式,來幫助 AddressBookfindContact() 得知:FindDialog 物件被關閉了。這將會在討論 findContact() 函式時進一步的解釋。



  在 findClicked() 中,我們確保使用者不會在沒有輸入一個聯絡人姓名時點擊 Find 按鈕。然後,我們將 findText 設為從 lineEdit 中取得的搜尋字串。之後,我們清除 lineEdit 的聯絡人,並隱藏對話視窗。

 void FindDialog::findClicked()
 {
     QString text = lineEdit->text();

     if (text.isEmpty()) {
         QMessageBox::information(this, tr("Empty Field"),
             tr("Please enter a name."));
         return;
     } else {
         findText = text;
         lineEdit->clear();
         hide();
     }
 }

  findText 變數有一個與之相關的公開獲取函數(getter function):getFindText()。之前我們僅在建構子與 findClicked() 函式中直接設置 findText,我們並沒有隨著 getFindText() 建立一個設置函式(setter function)。因為 getFindText() 是公開的,類別實體化與使用 FindDialog 總是能存取到使用者輸入並接受(accept)的搜尋字串。

 QString FindDialog::getFindText()
 {
     return findText;
 }


Defining the AddressBook Class

  為了確保我們能夠在我們的 AddressBook 類別中使用 FindDialog,我們在 addressbook.h 檔案中引入 finddialog.h

 #include "finddialog.h"

  到目前為止,所有我們的 Address Book 功能都有一個 QPushButton 和一個對應的 slot。同樣的,對於 Find 功能,我們有 findButtonfindContact()

  findButton 被宣告成一個私有變數,且 findContact() 函式被宣告成一個公開的 slot。

     void findContact();
     ...
     QPushButton *findButton;

  最後,我們宣告我們將會用以參照一個 FindDialog 實體的私有變數:dialog。

     FindDialog *dialog;

  一旦我們實體化一個對話視窗,我們將會不只一次地使用它;使用一個私有變數允許我們在類別中不只一個地方參照它。


Implementing the AddressBook Class

  在 AddressBook 類別的建構子中,我們實體化我們的私有物件,findButtonfindDialog

     findButton = new QPushButton(tr("&Find"));
     findButton->setEnabled(false);
     ...
     dialog = new FindDialog;

  接下來,我們將 findButton 的 clicked() signal 連接到 findContact()

     connect(findButton, SIGNAL(clicked()), this, SLOT(findContact()));

  現在所有剩下的就是我們 findContact() 函式的程式碼:

 void AddressBook::findContact()
 {
     dialog->show();

     if (dialog->exec() == QDialog::Accepted) {
         QString contactName = dialog->getFindText();

         if (contacts.contains(contactName)) {
             nameLine->setText(contactName);
             addressText->setText(contacts.value(contactName));
         } else {
             QMessageBox::information(this, tr("Contact Not Found"),
                 tr("Sorry, \"%1\" is not in your address book.").arg(contactName));
             return;
         }
     }

     updateInterface(NavigationMode);
 }

  我們藉由顯示 FindDialog 實體 dialog 開始。這是當使用者輸入一個聯絡人姓名供查閱的時候。一旦使用者點擊對話視窗的 findButton,對話視窗會被隱藏,且將結果代碼設為 QDialog::Accepted。這使得我們的 if 敘訴為真(true)。

  然後我們開始使用 FindDialoggetFindText() 函式取得搜尋字串--這個例子中的 contactName。假如聯絡人存在於我們的 Address Book,我們立刻顯示它。否則,我們顯示如下顯示的 QMessageBox 以告知它們的搜尋失敗。




來源:Address Book 5 - Adding a Find Function
版本:4.4.3

0 回覆:

張貼留言