♥ 學習筆記Learning 程式語言 Coding

[程式] C++ GUI Programming with Qt 4 ─ Chap 2. Creating Dialogs (中)

我們現在來看看FindDialog 類別的實作細節finddialog.cpp這個檔案。

 1: #include <QtGui>
 2: #include "finddialog.h"

首先,我們引入了<QtGui>,在這個標頭裡定義了不同的QT GUI 類別。QT包含很多種模組,每一種模組放置在他所屬的函式庫(library)‧當中最重要的模組是QtCore、QtGui、QtNetwork、QtOpenGL、QtScript、QtSql、QtSvg、QtXml。其中在 <QtGui> 標頭檔包含了QtCore 和QtGui部份模組中所有的類別定義‧引入這個標頭檔可以 幫助我們引入各種類別,又保持各自獨立。

finddialog.h,並非引入<QDialog> 和使用之前給QCheckBox、QLabel、 QLineEdit和 QPushButton, 的宣告,我們可以簡單的只引入<QtGui>。然而,從其他的標頭檔去引入一個大標頭檔並不是一個很好的寫法,特別是對大型的應用程式來說。

 3:  FindDialog::FindDialog(QWidget *parent)
 4:      : QDialog(parent)
 5:  {
 6:      label = new QLabel(tr("Find &what:"));
 7:      lineEdit = new QLineEdit;
 8:      label->setBuddy(lineEdit);
 9:      caseCheckBox = new QCheckBox(tr("Match &case"));
 10:      backwardCheckBox = new QCheckBox(tr("Search &backward"));
 11:      findButton = new QPushButton(tr("&Find"));

 12:      findButton->setDefault(true);
 13:      findButton->setEnabled(false);

 14:      closeButton = new QPushButton(tr("Close"));

第四行, 我們傳送了父參數(parent parameter)給基本的類別建構子(class constructor),然後我們可以創造一個子部件(Child Widget)。tr()函式將他所呼叫的字串標記起來並轉換成其他的語言。這個函式被宣告在QObject裡,而且每個子類別都包含了Q_OBJECT 巨集。用tr()去表達想讓使用者看見的字串是一個好習慣,即使你並沒有想要將應用程式的語言轉換成其他語言的計畫。在第18章,我們會介紹如何將QT應用程式轉換成其他語言。

在這個字串裡面,我們使用了&符號去表示快捷鍵(Shortcut keys)。舉例來說,第十一行建立了一個搜尋紐(Find button),可以讓使用者藉由在平台上輸入Alt+F快捷鍵去觸動。

&符號也可以被用來控制,在第六行我們建立了一個標籤使用快捷鍵(Alt+W),在第八行我們設置了標籤好友(Label’s buddy)為單行編輯器(line editor)。Buddy是一種用來接受快捷鍵訊息的部件(Widget),所以當使用者按下了Alt+W (標籤的快捷鍵),便會跳到所謂的標籤好友單行編輯器(label’s buddy)上。

在第12行,我們藉由呼叫setDefault(true)建了一個搜尋按鈕作為對話方塊預設按鈕,這個預設按鈕會在使用者按下Enter時被觸動。第13行,我們無法使用搜尋鈕,當這個部件(Widget)停用的時候,他通常會顯示為灰色,並且不會回應使用者的互動。

 

 15   connect(lineEdit, SIGNAL(textChanged(const QString &)),
 16           this, SLOT(enableFindButton(const QString &)));
 17   connect(findButton, SIGNAL(clicked()),
 18           this, SLOT(findClicked()));
 19   connect(closeButton, SIGNAL(clicked()),
 20           this, SLOT(close()));

 

在單行編輯器(line editor)出現文字改變的時候,私用訊息孔enableFindButton(const QString &) 會被呼叫。當使用者按下搜尋紐時,私用訊息孔findClicked() 也會被呼叫。當使用者按下Close後,這個對話方塊會自己關閉。close() 訊息孔(slot )繼承了QWidget,而且預設行為是將這個部件(Widget)隱藏起來。我們等下將會看看關於enableFindButton()findClicked() slots 的程式碼。

因為QObjectFindDialog的祖先之一,我們可以省略QObject::這些字眼connect()的前面。

 

 21:     QHBoxLayout *topLeftLayout = new QHBoxLayout;
 22:     topLeftLayout->addWidget(label);
 23:     topLeftLayout->addWidget(lineEdit);

 24:     QVBoxLayout *leftLayout = new QVBoxLayout;
 25:     leftLayout->addLayout(topLeftLayout);
 26:     leftLayout->addWidget(caseCheckBox);
 27:     leftLayout->addWidget(backwardCheckBox);

 28:     QVBoxLayout *rightLayout = new QVBoxLayout;
 29:     rightLayout->addWidget(findButton);
 30:     rightLayout->addWidget(closeButton);
 31:     rightLayout->addStretch();

 32:     QHBoxLayout *mainLayout = new QHBoxLayout;
 33:     mainLayout->addLayout(leftLayout);
 34:     mainLayout->addLayout(rightLayout);
 35:     setLayout(mainLayout);

接下來,我們使用排版管理去排版子部件(Child Widget)。排版可以包含所有的部件和其他的排版。巢狀的QHBoxLayouts、QVBoxLayouts和 QGridLayouts 將會被各自結合在一起,這可以是個非常複雜的對話方塊(Dialog)。

在Find對話方塊中,我們使用了 QHBoxLayouts 和 QVBoxLayouts的編排方式,如圖2.2所示。

外層的布局(layout)是最主要的,撰寫在第35行代表的是整個對話方塊的區域。

其他的三組布局(layout)屬於子布局,在按鈕的右邊的間隔區域可以用來拉長對話方塊。使用Find與Close按鈕底下的空間,可以用來確保這些按鈕有貼近頂部。

 

image Figure 2.2. The Find dialog’s layouts

有趣的是,排版管理類別並不是一個部件(Widget)。他並非來自QLayout,反而是由QObject所提供。如圖所示,部件(widgets)用實線表示,而佈局(Layouts)用虛線表示,用以區分兩者的不同。 對一個正在執行的應用程式來說,佈局(Layout)是看不見的。

當子佈局被加入到父佈局裡(第25、33和34行)時,子佈局會自動的被表示在父佈局之下。當對話方塊已經被設置好了主要佈局(行35),主要佈局將會成為對話方塊每個子佈局溝通方式。父子結構如圖2.3所描述。

 36:   setWindowTitle(tr("Find"));
 37:    setFixedHeight(sizeHint().height());
 38:  }

image
Figure 2.3. The Find dialog’s parent–child relationships

 

最後,我們將設置好對話方塊的標題(title),並且讓這個視窗有固定的高度,因為目前還沒有任何部件(Widget)可以有效的利用垂直空間。QWidget::sizeHint() 函式將會回傳一個部件(widget)理想的尺寸。

這樣就完成了FindDialog的建構子(Constructor)。因為我們使用new去建造這個部件的對話方塊和佈局,這樣看起來,我們需要寫一些解構子(Destructor)來刪除我們所建造的部件與佈局。但是這不是很必要,因為當父部件被關閉時,QT會自動刪除掉子物件(child objects );而且所有的子部件與佈局都是FindDialog的子孫。

本文是因為蕾咪愛睏會無法專心,所以乾脆邊讀邊做個小翻譯記錄,幫助理解,原文出自

C++ GUI Programming with Qt 4, Second Edition      by Jasmin Blanchette; Mark Summerfield

About the author

蕾咪

蕾咪,來自台東,卻不定期旅居歐洲的工程師女孩,身兼作家、部落客、創業家等多重身份。畢業於台大電子所,曾在義大利商與美商擔任研發工程師;走訪世界後,發現對台灣有段割捨不了的愛,讓我們一起努力成為想要的自己吧!:) 合作邀稿請聯繫:ramihaha@gmail.com

Leave a Comment