2月 14, 2009

【翻譯】Address Book 1 - Designing the User Interface

@
tutorials/addressbook/part1/addressbook.cpp
tutorials/addressbook/part1/addressbook.h
tutorials/addressbook/part1/main.cpp
tutorials/addressbook/part1/part1.pro

  這份指導的第一部分,涵蓋了我們使用在 Address Book 程式上的基礎圖形使用者介面(GUI,graphical user interface)設計。

  建立一個 GUI 程式的第一步,是設計使用者介面。在這一章,我們的目標是建立實現一個基礎的 Address Book 所需的標籤(label)與輸入區塊(input field)。下圖是我們期望的成果截圖。



  我們需要兩個 QLabel 物件(object):nameLabeladdressLabel,還有兩個輸入區塊:一個 QLineEdit - nameLine 和一個 QTextEdit - addressText,讓使用者能夠輸入連絡姓名以及住址。使用到的元件與它們的位置顯示在下圖。



  這裡使用了三個檔案來實現這個 Address Book:

  • addressbook.h - AddressBook 類別的定義檔,
  • addressbook.cpp - AddressBook 類別的實現檔,以及
  • main.cpp - 包含了一個 main() 函式,加上 AddressBook 實體(instance)的檔案


Qt Programming - Subclassing

  在寫 Qt 程式時,我們經常子類別化(subclass) Qt 物件以增加功能。這是建立自訂元件或是標準元件集合背後的其中一個基本要素。子類別化以擴展或改變一個元件的行為,有以下幾點好處:

  • 我們可以寫出虛擬(virtual)或是純虛擬(pure virtual)函式的實現以完全獲得我們的需求,在必要時則回頭採用基礎類別(base class)的實現。
  • 這允許我們封裝(encapsulate)部分的使用者介面在類別中,所以應用程式的其餘部分並不需要知道使用者介面中的獨立元件。
  • 子類別(subclass)可以在相同的應用程式或函式庫(library)中被用來建立多樣的自訂元件,且子類別的程式碼能夠在其他專案中被重複使用(reused)。

  由於 Qt 並沒有提供一個特有的 Address Book 元件,我們子類別化並加入功能到一個標準的 Qt 元件中。我們在這份指導教學中建立的 AddressBook 類別,在需要一個基礎 Address Book 元件的情況下可以被重複使用。


Defining the AddressBook Class

  addressbook.h 檔案被用來定義 AddressBook 類別。

  我們從將 AddressBook 定義為一個 QWidget 子類別與宣告(declare)建構子(constructor)開始。我們也使用了 Q_OBJECT 巨集(macro)以表示類別使用了國際化(internationalization)與 Qt 的 signal 與 slot 功能,即使我們在這一階段還不會使用到所有的功能。

 class AddressBook : public QWidget
 {
     Q_OBJECT

 public:
     AddressBook(QWidget *parent = 0);

 private:
     QLineEdit *nameLine;
     QTextEdit *addressText;
 };

  類別包含了 nameLineaddressText 的定義,也就是我們先前提到的 QLineEdit 與 QTextEdit 的私有(private)實體。在接下來的章節,我們將會發現將資料儲存在 nameLineaddressText 需要許多 Address Book 的函式。

  我們不需要包含我們將會用到的 QLabel 的定義,因為一旦它們被建立,我們就不需要再參照(reference)它們了。Qt 追蹤物件所有權(ownership)的方式會在下一節解釋。

  Q_OBJECT 巨集自身實現了一些 Qt 中較為進階的功能。目前,將 Q_OBJECT 巨集想成一個允許我們使用 tr()connect() 函式的捷徑(shortcut)是有用的。

  我們現在已經完成了 addressbook.h 檔案,讓我們繼續實現對應的 addressbook.cpp 檔案。


Defining the AddressBook Class

  AddressBook 的建構子接受一個 QWidget 參數(parameter)--父元件(parent)。照慣例,我們傳遞這個參數到基礎類別的建構子中。一個父元件可以擁有一個或多個子元件--這個所有權的概念,對於在 Qt 中組合元件是有用的。舉例來說,假如你刪除一個父元件,所有它的子元件也將會被刪除。

 AddressBook::AddressBook(QWidget *parent)
     : QWidget(parent)
 {
     QLabel *nameLabel = new QLabel(tr("Name:"));
     nameLine = new QLineEdit;

     QLabel *addressLabel = new QLabel(tr("Address:"));
     addressText = new QTextEdit;

  在這個建構子中,我們宣告並實體化兩個區域(local) QLabel 物件:nameLabeladdressLabel,並實體化了 nameLineaddressText。tr() 函式返回一個字串的翻譯版本,假如它是有效的;否則,它會返回字串本身。將這個函式想成一個 <在這裡插入翻譯> 記號以標記用以翻譯的 QString 物件。你將會注意到,在接下來的章節以及 Qt Examples 中,無論我們在何時使用一個可翻譯的字串,我們都會包含它。

  寫 Qt 程式時,瞭解佈局(layout)的運作是有用的。Qt 提供了三種主要的佈局類別:QHBoxLayoutQVBoxLayoutQGridLayout 來管理元件的位置。



  我們使用一個 QGridLayout 以結構化的方式擺放我們的標籤與輸入區塊到適當的位置。QGridLayout 將可用空間分割成一個網格(grid)並放置元件在我們指定行與列數的格子(cell)中。上方的示意圖顯示了佈局網格與我們的元件位置,我們使用接下來的程式碼來指定這個排列:

     QGridLayout *mainLayout = new QGridLayout;
     mainLayout->addWidget(nameLabel, 0, 0);
     mainLayout->addWidget(nameLine, 0, 1);
     mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop);
     mainLayout->addWidget(addressText, 1, 1);

  注意到 addressLabel 是利用 Qt::AlignTop 作為一個附加引數(argument)來做定位的。這用以確定它不會在格子 (1,0) 中垂直置中。參考 Layout Classes 文件,以獲得 Qt 佈局的基礎簡介。

  為了要將佈局物件設置到元件上,我們必須呼叫元件的 setLayout() 函式:

     setLayout(mainLayout);
     setWindowTitle(tr("Simple Address Book"));
 }

  最後,我們將元件的標題設為 "Simple Address Book"。


Running the Application

  一個獨立的檔案 main.cpp 用於 main() 函式。在這個函式中,我們實體化一個 QApplication 物件:app。QApplication 負責像是預設字體(font)和游標(cursor)等多種應用廣泛的資源,與執行事件迴圈(event loop)。因此,總是有一個 QApplication 物件在每個使用 Qt 的 GUI 應用程式中。

 int main(int argc, char *argv[])
 {
     QApplication app(argc, argv);

     AddressBook *addressBook = new AddressBook;
     addressBook->show();

     return app.exec();
 }

  我們使用 new 關鍵字,在堆積(heap)中建構了一個新的 AddressBook 元件,並呼叫它的 show() 函式來顯示它。然而,直到應用程式的事件迴圈開始前,元件還不會被顯示。我們藉由呼叫應用程式的 exec() 函式來開始事件迴圈;這個函式返回的執行結果同樣也作為 main() 函式的傳回值。


來源:Address Book 1 - Designing the User Interface
版本:4.4.3

0 回覆:

張貼留言