♥ 學習筆記Learning 程式語言 Coding

[程式] C++ GUI Programming with Qt 4 – Chap 2 Creating Dialogs (上)

這個章節將會教你如何使用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)的對話方塊。

image

這個原始檔將包含兩個檔案,finddialog.hfinddialog.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::CaseSensitiveQt::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

About the author

蕾咪

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

Leave a Comment