這個章節將會教你如何使用QT來做出對話方塊(Dialog);所謂的對話方塊(Dialog),主要是讓使用者可以擁有選項或設定參數的機會;之所以稱為對話方塊的原因是,這是一個讓使用者(user)與應用程式(application)能夠互動的方式。
大部分的GUI應用程式,包含了具有選單和工具列的主要視窗(Main Window),藉由幾十個對話方塊(Dialog)來支援主要視窗(Main Window)的功能。對話方塊(Dialog)也可以馬上回應使用者的需求去表現出適當的反應。
我們將寫程式碼建立第一個對話方塊(Dialog)來示範這是如何實作出來的;接著,我們將看到如何使用QT Designer去建立對話方塊(Dialog);QT是一個所見即所得的工具,使用QT Designer會比自己撰寫程式碼快很多,並且可以很簡單的測試不同設計。
QDialog的子類別(Subclassing QDialog)
我們的第一個例子是完全用C++撰寫的Find對話方塊(Dialog),由下圖所示。我們將會實作這個對話方塊(Dialog)做為一個類別(class),藉由這樣的做法,我們可以做出一個獨立的、完備的(self-contained)元件,擁有自己訊號與訊息孔(Signals and slots)的對話方塊。
這個原始檔將包含兩個檔案,finddialog.h 與 finddialog.cpp. 我們將從finddialog.h 開始。
1: #ifndef FINDDIALOG_H
2: #define FINDDIALOG_H
3: #include <QDialog>
4: class QCheckBox;
5: class QLabel;
6: class QLineEdit;
7: class QPushButton;
第一行與第二行是為了保護標頭檔(header file)不會重複的被引用。
第三行包含了一個<QDialog>標頭檔,裡面包含了對話方塊(Dialog)的定義,這是QT的基本類別。
第四行到第七行宣告了一些類別(class),我們要用他們來實作對話方塊(Dialog),預先宣告會告訴編譯器(Compiler)這些類別的存在,沒有給太多的細節,我們會很快會解釋為何是這樣。
接下來,我們定義FindDialog做為一個QDialog的子類別(subclass) 。
8: class FindDialog : public QDialog
9: {
10: Q_OBJECT
11: public:
12: FindDialog(QWidget *parent = 0);
Q_OBJECT在類別的一開始就定義是必要的,因為它定義了所有類別的訊號與訊息孔功能(Signal and Slot);FindDialog的結構是典型的QWidget類別,需要指定父類別參數(parent parameter),這裡的預設值是空,代表的是這個對話方塊(Dialog)沒有父類別。
13: signals:
14: void findNext(const QString &str, Qt::CaseSensitivity cs);
15: void findPrevious(const QString &str, Qt::CaseSensitivity cs);
在訊號(signals)這段宣告了兩種訊號(signals),這兩種訊號會在使用者按下搜尋(Find)按鈕時發送。
如果往前搜尋是觸發的,這個對話方塊(Dialog)會發送findPrevious(),否則會發送findNext()。
這個訊號關鍵字實際上是一個巨集(Macro)。在編譯之前,C++預載器(Preprocessor)會轉換訊號(Signal)變成標準的C++。Qt::CaseSensitivity 是一個列舉型別(enum),可以得到Qt::CaseSensitive 和Qt::CaseInsensitive的值。
16: private slots:
17: void findClicked();
18: void enableFindButton(const QString &text);
19: private:
20: QLabel *label;
21: QLineEdit *lineEdit;
22: QCheckBox *caseCheckBox;
23: QCheckBox *backwardCheckBox;
24: QPushButton *findButton;
25: QPushButton *closeButton;
26: };
27: #endif
在私用(private)類別段落,我們宣告了兩個訊號孔(Slots)。為了實作出訊號孔(Slot),我們將需要存取對話方塊的子部件(Child Widget),所以我們需要維護好他的指標(pointer)。訊號孔(Slot)關鍵字,跟訊號很像,是一種擴展成結構的巨集,並且可以被C++的編譯器給解讀。
我們使用之前宣告的那些類別在私用變數(private variables)上,可以這樣做的原因是他們都是指標,而且我們沒有在標頭檔存取他們,所以編譯器並不需要完整的類別定義。
我們一樣可以去包含那些相關的標頭檔(<QCheckBox>, <QLabel>, etc.),但是使用預先宣告(forward declarations)是有可能使得編譯速度變快的。
—
本文是因為蕾咪愛睏會無法專心,所以乾脆邊讀邊做個小翻譯記錄,幫助理解,原文出自
C++ GUI Programming with Qt 4, Second Edition by Jasmin Blanchette; Mark Summerfield