用 QT Designer 來快速學習 QT


作者﹕GoldenCat <ruili@worldnet.att.net>
寫在前面: 這裡只是告訴大家一種如何快速學習 QT 的方法.這裡也只對 QT Designer 和 QT 作一個簡單的介紹.讓沒有寫過 QT 的人能對 QT 有一個初步的認識. 如果您 真的對 QT Programming 很有興趣.這裡我建議您去看看 O'REILY 出版的 Programming with QT 和 Bible 出版的 KDE 2 /QT Programming. 這兩本書將會給您帶來一個好的 開始. 這篇文章適合您嗎? 這篇文章只是對 QT 的一個入門介紹.如果您有興趣認識一下 QT 這種語言,那麼 這篇文章就很適合您了. 如果您對 C++ 能有一些的了解,那麼您將會很輕鬆的看完這篇文章. 如果您什麼 程式語言也沒有學過.但也想一窺 QT 的容貌.那麼也沒有關係.這裡都是些非常間單的東西. 也需會成為您學習寫程式的一個起點. 如果您本身已經在開發、學習 QT/KDE 或者 Xwindow 有關的程式設計.那就只能當 是打發時間看看玩了.這篇短短的文章沒有寫到很多的東西. 對於這些高手們,我唯一能提共 的一個經驗就是多多去看 $QTDIR/include 下面的東西. 1. 什麼是 QT. 用 Linux 的人,一定都知道 QT 是什麼.而利用 QT 編譯出來的 KDE 桌面系統, 更是讓 Linux 有了一次能和 Windows 的 GUI 相媲美的機會.甚至有人說, KDE 的桌面在圖形上,還勝過了 Windows95 了.那麼 QT 到底是什麼呢?其實 QT 就是基於 C++ 語言上的一種專門用來開發 GUI 介面的程式.這裡面包括了: button; label; frame ... 等等很多的可以直接調用的東西. 2. 為什麼選擇 QT 2.1 QT 是基於 C++ 的一種語言 相信 C/C++ 目前還是一種很多人都在學習的語言. QT 的好處就在於 QT 本身 可以被稱作是一種 C++ 的延伸. QT 中有數百個 class 都是用 C++ 寫出來的. 這也就是說, QT 本身就具備了 C++ 的快速、簡易、Object-Oriented Programming (OOP)等等無數的優點. 2.2 QT 具有非常好的可移植性(Portable) QT 不只是可以在 Linux 中運作.也同樣可以運行在 Microsoft Windows 中.這也就 意味者,利用 QT 編寫出來的程式,在幾乎不用修改的情況下,就可以同時在 Linux 中和 Microsoft Windows 中運行. QT 的應用非常之廣泛,從 Linux 到 Windows 從 x86 到 Embedded 都有 QT 的影子. 3. 什麼是 QT Designer 簡單的來說 QT Designer 是一個 GUI 的工具. 這個工具可以幫助我們來加快寫 QT 程式的速度. 利用 QT Designer 可以用一種所見既所得的方式,來產生 QT 程式的 GUI 介面的程式碼. 通過增加一些功能,就可以完成一個程式了.利用 QT Designer 可以非常快速的學會 QT, 而我們這裡說利用 QT Designer 來學習 QT 而不是利用 QT Designer 來寫 QT, 這裡的區別就在於, QT Designer 所產生的程式碼有些繁瑣. 跑起來也比較的慢些.我們這裡只是利用 QT Designer 來幫助我們學習.而不是直接 去跑 QT Designer 生成的程式碼. 3. 基本要求 因為這篇文章主要是告訴大家如何利用 QT Design 來達到快速學習 QT 的. 所以您最也要做到: 您需要有一台可以跑 Linux 的電腦或者 Microsoft Windows 的電腦 足夠的 RAM 和 HardDisk 用以安裝、 編譯 QT 您的 Linux 中需要安裝有 KDE、QT、QT Designer、g++ 等等程式. 您如果適用 Microsoft Windows, 則您需要 VC++ 和 QT For Windows Linux 的使用者最好還能安裝一個 Kdevelop(一個非常好的用來開發 QT 的 Develop Enverment) 4. QT Designer 簡單的介紹--從 PushButton 開始 假設您一切都安裝好了.現在我們打開 QT Designer 吧. 打開後,選擇 New -> Dialog 這時侯,您的 QT Designer 中就會出現一個 From1 來. 現在我們 click 一下上面的 tools 中 的那個 pushbutton, (標有 OK 的圖標)並且用 mouse 選擇到一定的大小. 在這個 pushbutton 上面用您的 mouse double click 一下. 我們就可以改變 pushbutton 的 label 了. 這裡我們把 pushbutton1 這幾個字,換成 Exit, 然後直接按 Enter 或者用 mouse 選擇 OK 也可以. 現在我們 看到, 那個 button 中的標籤已將變成 Exit 了. 我們這時侯還需要給這個 Exit Button 一個 signal(信號), 這樣當您在 Exit 這個 Button 上 click 的時侯. QT 才知道如何去處理這個信 號. 我們按一下 F3(connect singnal slot)然後在那個 Exit Button 上面 Click 一下. 這時 侯我們就看到了 Edit Connection 的 Dialog 了. 在 Signal 中選擇 clicked, 在 slot 中,先選 擇 setFocus() 就好了. 這時侯選擇 OK. 我們就算是完成了. 如果想看看這個小程式長什麼樣子. 可以用 CTRL+T來看 PreView. (see figure 1)
figure 1
首先在您的 $HOME 中建立一個 qt_program 的 Directory 出來. 這個 Directory 將會 作為我們存放文件的地方. 現在我們用 File -> Save 把這個文件存為 form1.ui 放在 $HOME/qt_program 的目錄下.現在如果大家打開 form1.ui 來看一看. 會發現那是一堆有很多 <tag&g; 的不知道是什麼 的東西.所以我們需要用一個叫做 uic 的程式來把 .ui 文件轉換成 QT 可以使用的 .cpp 和 .h 文件. 用下面的指令就可以生成我們需要的 .h 文件了 uic -o form1.h form1.ui 而生成 .cpp 文件則需要用以下的指令: uic -i form1.h -o form1.cpp form1.ui 這時侯,form1.h中就會看到一個標準的 QT 需要的 .h 文件 1. #ifndef FORM1_H 2. #define FORM1_H 3. #include <qvariant.h> 4. #include <qdialog.h> 5. class QVBoxLayout; 6. class QHBoxLayout; 7. class QGridLayout; 8. class QPushButton; 9. class Form1 : public QDialog 10. { 11. Q_OBJECT 12. public: 13. Form1( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ); 14. ~Form1(); 15. QPushButton* PushButton1; 16. }; 17. #endif // FORM1_H 1-2: 定義 FORM1.H 這個文件 3-4: 這裡是我們需要用到的兩個 .h 文件 5-7: 我們根本用不到, qt designer 自己產生的 8: QPushButton 需要用到這個 class 9-11: 我們的 form1 是 based 在 QDialog 上面的 12: 公開的 (可以在以後的程式中使用.用過 C++ 的人一定明白) 13: Form1的架構 14: 清除 Form1 15: 產生一個pushbutton (就是那個標有 exit 的 按鈕 17: 結束對 FORM1.H 的定義 而 form1.cpp 文件如下: 1. #include "form1.h" 2. #include <qpushbutton.h> 3. #include <qlayout.h> 4. #include <qvariant.h> 5. #include <qtooltip.h> 6. #include <qwhatsthis.h> 7. /* 8. * Constructs a Form1 which is a child of 'parent', with the 9. * name 'name' and widget flags set to 'f' 10. * 11. * The dialog will by default be modeless, unless you set 'modal' to 12. * TRUE to construct a modal dialog. 13. */ 14. Form1::Form1( QWidget* parent, const char* name, bool modal, WFlags fl ) 15. : QDialog( parent, name, modal, fl ) 16. { 17. if ( !name ) 18. setName( "Form1" ); 19. resize( 596, 480 ); 20. setCaption( tr( "Form1" ) ); 21. PushButton1 = new QPushButton( this, "PushButton1" ); 22. PushButton1->setGeometry( QRect( 130, 160, 161, 71 ) ); 23. PushButton1->setText( tr( "Exit" ) ); 24. // signals and slots connections 25. connect( PushButton1, SIGNAL( clicked() ), PushButton1, SLOT( setFocus() ) ); 26. } 27. /* 28. * Destroys the object and frees any allocated resources 29. */ 30. Form1::~Form1() 31. { 32. // no need to delete child widgets, Qt does it all for us 33. } 1: 我們上面的定義文件 2: pushbutton所需要的 .h 文件 3-6: 我們根本用不到, qt designer 自己產生的 7-13: QT Designer 產生的註解 14-15: Form1 的結構 17-18: 如果Form1:Form1中沒有 pass 一個名子過來.那麼就命名為 Form1 19: resize 20: 把顯示出來的那個 Dialog 的名子定為 Form1, 也就是 window 中左上角的字 21: 做出一個新的button,名子為 PushButton1 22: 這裡設定了 pushbutton 在這個 dialog 中的位置. Qrect(130, 160, 161, 71) 這裡是說在一 個Dialog中,以左邊最上面來算,位置是(0,0), 所以說,這裡的130(橫向)和 160 (縱向)就是說我 們從 (0,0)開始,往左邊跑130,往下跑 160.這樣我們就算出了pushbutton這個按鈕畫在那裡了.後面的161, 71則是定義這個pushbutton到底要畫多大,設定了長和高 23: 通過呼叫setText指令,我們可以在這個 button上面給入我們需要的文字.這裡是 Exit 24: QT Designer 產生的註解 25: 上面就是處理當接收到 clicked 的信號(singal)以後,我們所作的事情(setFocus on PushButton1) connect 這裡是告訴程式連接一個信號,PushButton1, SIGNAL(clicked()),是說信號是由 PushButton1 發出, 發出的信號為 mouse clicked,PushButton1, SLOT(setFocus())表示信號發出以後,目標(Object)為 PushButton, event 是 setFocus() 動作 26: 主程式結束 27-29: QT Designer 的註解 30-33: 清除 Form1 由於我們要常常用到 QT Designer, 也就是說,需要常常用到 uic 這隻程式. 為了省去每次都要 打一堆東西的麻煩.我們來寫一各小 script 來處理 .ui 檔案. 不難看出, uic 在處理/生成 .h .cpp 檔案的時侯,用到了兩個指令: uic -o form1.h form1.ui uic -i form1.h -o form1.cpp form1.ui 所以我們的 script 就寫成: ############################################################### #!/bin/sh # # myuic program convert .ui to .cpp .h by calling uic # # INPUT_UI=$@ # #這裡讀取外面傳回來的文件名 # # # if [ ! -f "$INPUT_UI" ] # then # echo "UIC File $INPUT_UI Not Found" # echo # echo "Userage myuic input_file.ui" # echo # exit 1 # fi # #上面的語句檢查我們所輸入的.ui文件是否存在 # #如果找不到指定的.ui文件,則顯示一個簡短的 # #使用說明 # # INPUT_H=`echo $@ | cut -d '.' -f1`.h # #這裡我們利用 cut 來處理輸入的 .ui 文件. # #得到一個 .h 的文件名 # # INPUT_CPP=`echo $@ | cut -d '.' -f1`.cpp # #同樣的道理,利用 cut 產生一個 .cpp 的文件名 # # uic -o $INPUT_H $INPUT_UI # #這裡就是利用 .ui 產生 .h 的文件 # # uic -i $INPUT_H -o $INPUT_CPP $INPUT_UI # #利用 .h 和 .ui 產生 .cpp 文件. # # ############################################################### 我門把這個文件存為 myuic. 並切 chmod +x 變成可執行檔案. 然後 cp 到 /usr/bin 上面. 如果您在電腦中沒有 root 的權限. 可以在自己的 $HOME 目錄中做一個 bin 的 Directory 出來. 然後去編輯您的 .bash_profile (這裡假設您用的是 bash) 如果您的 .bash_profile 中本身已經有了 PATH 這段文字,那麼 您只要在原本的 PATH 後面加上 :$HOME/bin就可以了.如果沒有 那麼就在您的 .bash_profile 中寫入: PATH=$PATH:$HOME/bin export PATH 這樣您以後就可以直接執行 myuic 這個文件了.現在試試看用 myuic 來處理 剛剛的那個 form1.ui 這個文件吧. 先把舊的 .h .cpp 都刪除掉: rm -f *.cpp *.h 然後用 myuic 來生成新的 .cpp .h 文件: myuic form1.ui 這時候用 ls 就會看到 form1.cpp form1.h form1.ui 這三個文件了 這時侯我們只需要寫一個小的main.cpp就可以編譯form1.cpp了. main.cpp非常的簡單 #include "form1.h" #include <kapp.h> int main(int argc, char **argv) { KApplication app(argc, argv, "Form1"); //KDE 是建立在QT的基礎上得所以KApplication //所以kapp.h實際上包含了qapplication.h Form1 *form1=new Form1(); form1->show(); app.setMainWidget(form1); return(app.exec()); } 基本上來說,很簡單.然後當然就是編譯啦.我建議寫出來的東西都用 Kdevelop 來解決.首先 Kdevelop 介面非常的友善.又能省下寫 Makefile 的麻煩.打開 Kdevelop 以後,選擇 項目->新建, KDE2-Normal, 然後 選擇 Next,在這一頁中.注意不要在任何選項中打"x",因為我們用不到.反而會增加麻煩.最後 一直 next,然後 create , exit. 這時侯我們就已經有一個新的項目可以用了.在 menu 中選擇: 項目->添加現存文件.然後把 qt_program 中的 form1.cpp form1.h 和 main.cpp 加入. 這時候只要按 一下 F9 , Kdevelop 就會自動幫您把程式 compile 出來.並且執行. 程式執行後,我們不能用 click 那個 Exit Button 退出程式.因為我們並沒有給他退出的信號.現在讓我們來把程式碼作些改動: ########################################################### #form1.h #ifndef FORM1_H #define FORM1_H #include <qdialog.h> class QPushButton; class Form1 : public QDialog { Q_OBJECT public: Form1(QWidget *parent=0, const char *name=0); QPushButton* PushButton1; }; #endif // FORM1_H ################################################################# #form1.cpp #include "form1.h" #include <qpushbutton.h> #include <kapp.h> Form1::Form1(QWidget* parent, const char* name): QDialog(parent, name) { setCaption(tr("Form21")); PushButton1=new QPushButton(this,"PushButton1"); PushButton1->setGeometry(QRect(130,160,161,71)); PushButton1-vsetText(tr("Exit")); connect(PushButton1, SIGNAL(clicked()), kapp, SLOT(quit())); } Form1::~Form1(){} #################################################################### main.cpp 保持不變.經過一番簡化.程式碼馬上簡單很多了. 這裡我們除了把一些由 QT Design 做出的不必要的 code 挑除以外.對 form1.cpp 做了兩個小改動. 1.增加了 #include <kapp.h>這個 head file. 2.我們把: connect(PushButton1, SIGNAL(clicked()), PushButton1, SLOT(setFocus())); 改變為 connect(PushButton1, SIGNAL(clicked()), kapp, SLOT(quit())); 同樣的信號傳送,但是目標對象有所改變.現在目標將作用在 kapp 上面也就是我們 的主程式(main application),而 SLOT 則是呼叫 quit(),現在 Kdevelop 中更改 程式碼.然後按下 F9 .等待程式運行.這時侯我們的程式,只要在那個 Exit 的 Button 上面用 mouse click 一下. 這個程式就完全關閉了. 現在我們在這個 PushButton 中再增加一些功能.我們來看看 QT Designer 中的 ToolTip 功能. 如果您的 QT Designer 中 Property Edit 並沒有自動出現.那麼請在 QT Designer 中選擇 Menu 中的 Windows 然後選擇 Property Edit. 只要在 PushButton1 那個 Button 上面用 mouse click 一下. 就可以對 Pushbutton1 的 Property 進行編輯. 在 Property Edit 中的 ToolTip 後面可以進行文字輸入的地方,打入下面的文字: Click On this Button Will Exit Main Window. 然後 sava 文件. (Form1.ui)在用我們的小 script 呼叫 uic 程式把, Form1.ui 轉成 Form1.h 和 Form1.cpp myuic form1.ui 這時侯我們來觀察生成的 form1.cpp 文件,我們會發現現在這裡面比一前多了些東西. 現在這裡多了一行: QToolTip::add( PushButton1, tr( "Clicke On this Button Will Exit Main Window." ) ); 這裡,我們用QToolTip中的add,在 Object (PushButton1) 上面加入"Clicke On this Button Will Exit Main window."這個字幕.現在我們在前面那個被我們簡化的 form1.cpp 中,加入上面那 行程式碼,因為我們需要調用到 QToolTip 所以我們也要把 qtooltip.h 給 include 進去. ################################################################# #form1.cpp #include "form1.h" #include <qpushbutton.h> #include <kapp.h> #include <qtooltip.h> //因為我們需要用到QToolTip所以,這裡要加入qtooltip.h Form1::Form1(QWidget* parent, const char* name): QDialog(parent, name) { setCaption(tr("Form21")); PushButton1=new QPushButton(this,"PushButton1"); PushButton1->setGeometry(QRect(130,160,161,71)); PushButton1->setText(tr("Exit")); QToolTip::add(PushButton1, tr("Click On this Button Will Exit Main Window.")); connect(PushButton1, SIGNAL(clicked()), kapp, SLOT(quit())); } Form1::~Form1(){} #################################################################### 這時侯,重新編譯這個 form1 的程式.您就會看到,當您把 mouse 移動到 Exit 那個按鈕的時侯. 停留差不多一兩秒鐘. "Click On this Button Will Exit Main Window"的字樣就會出現. QPushButton 中還有一個常用的功能就是 setEnabled 了.setEnabled 通過 TRUE 和 FALSE 這兩 個值.可以決定這個扭是否可以被使用者按下. 我們現在在 QT Designer 中的 Property Edit 中把 Enable 選擇成 FALSE, 然後用 myuic 生成 新的程式碼. $myuic form1.ui 這時候再去觀察 form1.cpp 會發現裡面多了一行 PushButton1->setEnabled( FALSE ); 這一行就 把 PushButton1 設置為不可使用了. 如果需要 PushButton1 可以正常的被 Click, 那麼只要用 PushButton1->setEnabled(TRUE) 就可以了. 提示: 最常用的作法通常是做出一個 SLOT 或者一個判斷語句,來設定 PushButton 的狀態. QPushButton 還有一各場常被用到的功能就是 Font (字體的設定)在 QT 中,我們通過 QFont 可以 設定字體的大小,種類. 在 QT Designer 中的 Property Edit 中.有一個 Font 的選項.我們在 Font 後面的那個 ... 上面 按一下,就會出現一個可以選擇 font 的 window. 這裡我們以 Courier(adobe) 24 號字為例子.選擇 後, Save, 然後觀察重新用 uic 生成的 .cpp 程序碼. 我們會發現主程式中多出了下面這些程式碼: QFont PushButton1_font( PushButton1->font() ); PushButton1_font.setFamily( "adobe-courier" ); PushButton1_font.setPointSize( 24 ); PushButton1->setFont( PushButton1_font ); 後面還多出一個 bool Form1::event( QEvent* ev ). 這裡我們先不要去理會 bool Form1::event( QEvent* ev ) 只看下面這四行就好了: 1. QFont PushButton1_font( PushButton1->font() ); 2. PushButton1_font.setFamily( "adobe-courier" ); 3. PushButton1_font.setPointSize( 24 ); 4. PushButton1->setFont( PushButton1_font ); 第一行是用 QFont 生成 PushButton1_font. PushButton1_font 是為了給 PushButton1 做字體設定 第二行是告訴 PushButton1_font 使用那種字型. 我們這裡使用的是 adobe-courier 第三行用了 setPointSize 設定了我們需要用到多大的字,這裡我們用的是 24 號字. 第四行就真正的把這些值給到了 PushButton1 中.也就是說告訴 PushButton1 去改變字體的顯示. 加入下面的代碼以後,重新編譯 form1, 就會看到那個按鈕中的 Exit 這幾個字明顯的變大了.字體也改變 了. 提示: 通常在設定字體的時侯.都是用 #define 的方式在文件的開頭宣告出來. 例如 #define FONT_SIZE 24 然後在設定時用 PushButton1_font.setPointSize(FONT_SIZE) 這樣當您要改字體的時侯,只要把 #define FONT_SIZE 後面的值改了 整個程式中所有的字體就都改變了.而省去了在需要改變字體的時侯, 一個個的去改變沒一個 setPointSize中的值 ˇ PushButton 是非常之常用的一個東西.可以說是任何程式都不可少的.通常最常見 的用途就是作為 "退出" 按鈕,對話窗口的選擇按鈕等等. QLabel 的使用: 現在我們再來看看 QLabel 的用法. 在 QT Designer 中, 用 Mouse 選擇 Text Label,(就是那個 畫了個『A』的圖標.)然後用 Mouse 畫出一個隨便大小的 Text Label. 再用 Mouse 在這個 Label 上面 Double Click 一下.將跳出的 Window 中的那個 TextLabel1 改成 My Label. 然後按 Save 保存文件. 用 uic 轉成 .cpp 和 .h 文件.這使侯,我們發現,在 .h 文件中,多出了 class QLabel; //這裡告訴程式,我們下面需要用到 QLabel QLabel* TextLabel1; // 用 QLabel 生成 *TextLabel1 在 .cpp 中,我們則看到了多出下面這些東西. #include <qlabel.h> //這就不用我多說了吧, include 進 qlabel.h 因為我們的 QLabel 需要 TextLabel1 = new QLabel( this, "TextLabel1" ); //定義 TextLabel1 TextLabel1->setGeometry( QRect( 130, 120, 171, 91 ) ); //設定 TextLabel 的位置 TextLabel1->setText( tr( "My Label" ) ); // 還既得我們輸入的 My Label 吧.也就是給 TextLabel1 定的 //顯示出來的東西.就是用 setText 在這裡設定的. 現在我們把這些加入到我們前面寫的那個程式中.將上面的東西加入到 form1.h 和 form1.cpp 中. 不過我們這裡需要做一點小小的改變.就是把 TextLabel1 的位置遠一下.放造屏幕的最左上角. 我門把: TextLabel1->setGeometry( QRect( 130, 120, 171, 91 ) ); 改換成: TextLabel1->setGeometry( QRect( 0, 0, 171, 91 ) ); 重新編譯我們的程式.就會看到在程式窗口的最左上角,有一排文字的出現.文字就是我們的 TextLabel 中 定義的 "My Label". 現在回到我們的程式部份.在前面的 PushButton 中,我們給我們的 PushButton 定義了字型及字體.實際 上,字型及字體的定義.在 QT 中是通用的. 我們可以用一樣的方法來定義 QLabel 的字體.我們現在在程式 中加入: QFont TextLabel1_font( TextLabel1->font() ); TextLabel1_font.setFamily( "adobe-courier" ); TextLabel1_font.setPointSize( 24 ); TextLabel1->setFont( TextLabel1_font ); 這樣我們就把這個 TextLabel改成了跟前面 PushButton 一樣的字體 courier (adobe) 24 號字. 大家常常能看到 QT 中的 TextLabel 是用圖片來顯示的.實際上,這也很簡單.我們在 QT Designer 中, 首先在我們剛剛生成的那個 TextLabel 上面用 Mouse Click 一下.把 Property Edit 的 Focus Set 到 我們得 TextLabel 上面. (如果您剛剛沒有用 Mouse 在您的 QT Designer 上面亂按的話.那麼您的 Property Edit 中的 Focus 應該本身就已經在 TextLabel 上了)這時侯,我們在 Property Edit 中找一個叫做 pixmap 的東西.在 pixmap 後面的 『...』中按一下,就出現了一個新的讓您還則圖片的視窗. QT Designer 中 目前可以接受的圖片格式為(這篇文章用的是 QT Designer 1.1)bpm, jpeg, pbm, pgm, png 和 ppm. 所以 大家隨便找一個上面格式的圖片.然後選擇 OK.這時侯您就會發現那個 TextLabel 變成您選擇的圖片了. 也許 您會發現,圖片並沒有完全顯示出來,而是只顯示了一部分.(如果您選擇的圖片大過您的 TextLabel 的話)這 是很常見的.在 pixmap 底下,有一個 scaledContents 的選項.只要把選項後面的值改成 True 就好了.這時侯 您看到的就是一個經過平衡收放過大小的圖片了. 保存 (Save)起來.讓我們來看看程式碼這邊是如何處理這 些圖片的吧. 首先我們看到的是在 .cpp 的文件中,多出了: #include <qimage.h> #include <qpixmap.h> 這兩個文件.這些都是處理圖片時需要的. 後面也許大家就頭大了. static const char* const image0_data[] = { xxxxx xxxxx xxxxx xxxxx ...... ...}; 好長的一段.這些是什麼呢?看上去滿複雜的.不用懷疑,這就是您放進去的那個圖片.只不過這裡是用 xpm 的格式來處存的. 什麼事 XPM 呢? 其實 XPM 是 XPixMap的簡稱. XPM 是 Linux 中 X11 的一種圖像處存的方法. 在 XPM 中,圖像被允許用 ASCII 文字模式來保存起來. 而 XPM 的另一個特性就是可以 直接被 C Compiler 所接受.也就是說您可以直接把 XPM 的圖片編譯到您的程式中. 把 XPM 直接編譯到程式中有兩個最大的好處: 第一點是程式本身如果有很多圖片,用 XPM 全部編譯進程式中.就避免了在發行程式得時侯,需要附帶很 多圖片的麻煩. 第二點就是「相對」來說,被編譯進程式的圖片,對於一般的普通使用者來說,要改起來會比較麻煩些. 當然,如果說您不准發行Open Source Code的程式.在沒有 Source Code 的情況下.想要改您放放入的 圖片,就更家困難了. 但是相對的,也有一些不便性: 程式碼本身會加大很多 圖片的更改性不靈活 接下來,我們看到了下面的程式碼: QPixmap image0( ( const char** ) image0_data ); \\image0_data 就是前面那個 XPM 的圖片啦 TextLabel1->setPixmap( image0 ); \\ 這裡是告訴 TextLabel1 去使用並且顯示 image0 (image0_date) TextLabel1->setScaledContents( TRUE ); \\打開自動平衡收放圖片大小的功能. QPixmap 本身其實就接受 xpm 檔案. 所以我們可以不用把 XPM 的 Source 編譯進程式中.而改用 QPixmap pixmap("image.xpm")的形式.當然,我們需要把圖片文件轉換成 XPM 的格式.這裡我們用 到了 Linux 中本身為我們準備好的工具 convert. convert 本身支持非常多的圖片各式的轉換. 如果您有興趣,可以用 man convert 來看看 convert 的詳細內容.這裡我只介紹如果把一個圖片文 件轉換成 xpm 的格式.我選擇的是 Linux 中的代表圖片.一隻可愛的小企鵝--logo.gif,相信每一個 安裝了 linux 的人,應該都可以找到這個圖片吧.您可以試這用 locate logo.gif 來尋找.找到以後, 把 logo.gif 複製到程式放有 form1 程式碼的目錄下. 然後用下面的指令來作圖片的格式轉換: convert logo.gif logo.xpm 這時侯,我們就可以看到目錄中多了一個 logo.xpm 的文件了. 現在我們回到我們的 form1 程式碼中.在前面加入 #include <qpixmap.h> 然後在 TextLabel的後面任何地方,加入下面三行程式碼: QPixmap pixmap("logo.xpm"); //這裡就是告訴 pixmap 我們剛剛 convert 出來的那個圖片 TextLabel->setPixmap(pixmap); //讓 TextLabel 調用/顯示 pixmap (logo.xpm) TextLabel->setScaledContents( TRUE ) ; //打開自動平衡收放圖片大小的功能 記住喔,一定不能在 TextLabel = new QLabel( this, "TextLabel1" ); 以前加入喔! 這時侯重新編譯我們的程式碼,在新的程式中,您就可以看到那隻可愛的小企鵝了.您也許 會發現企鵝胖的有點變形.那是因為自動平衡是根據您的 TextLabel 的大小來收放圖片的. 所以我們只要把: TextLabel1->setGeometry( QRect( 0, 0, 171, 91 ) ); 改換成: TextLabel->setGeometry( QRect( 0, 0, 171, 191 ) ); 也就是說把高度增加 100,重新編譯以後.可以看到,企鵝的大小變得正常多了. ˇ Label 也是最常用的組件.通常被用為在視窗中的文字顯示. RadioButton 的簡介: 接下來讓我慢看看 RadioButton. 在 QT Designer 中,有一個圓圈圈的圖案,在圓圈中 有個黑色的實心圓圈.那個就是 RadioButton 了.現在我們在我們的 form1 中,增加一個 RadioButton. 然後來觀察程式碼. 在 .h 文件中,多出了兩行 class QRadioButton; //告訴程式我們需要用到 QRadioButton 和 QRadioButton* RadioButton1; //QRadioButton *RadioButton1 在 .cpp 的文件中出現了下面三行程式碼,以及一個 include 文件 #include <qradiobutton.h> //QRadioButton 所需要的 include 文件 RadioButton1 = new QRadioButton( this, "RadioButton1" ); //生成一個新的 QRadioButton 在介面 this上 // this 就是只當前的主介面.也就是我們的 // Form1 : public QDialog // 白話文的方法來說呢,就是我們這個程式的 // 主顯示視窗.相信大家已定很熟習了吧. RadioButton1->setGeometry( QRect( 260, 60, 151, 61 ) ); // 通過 setGeometry(QRect()) 來設定我們這個 // RadioButton 的大小 RadioButton1->setText( tr( "RadioButton1" ) ); // 用 setText() 來給我們的這個 RadioButton // 命名.這裡這裡名為 "RadioButton1" 將上面這些程式碼加入到我們的 form1.h 和 form1.cpp 中,重新編譯程式,我們就看到了一個名為 RadioButton1 的 RadioButton 了. RadioButton 除了可以用到 PushButton 中的 setEnabled( FALSE )的選項來 Disable 這個 RadioButton 以及在 QT 中通用的 setFont 以外,還提共一個非常常用的 setChecked (TRUE/FLASE) 功能. 在 QT Designer 中, 用 mouse click 一下我們剛剛生成的那個 RadioButton, 然後在 QT Designer 的 Property Edit 中.選擇 checked, 在 checked 後面選擇 True. 經過 uic 程式以後,重新觀察 .cpp 程式 碼, 您會發現,在 .cpp 文件中,多出了一行: RadioButton1->setChecked( TRUE ); //這行就設定了, RadioButton1 在程序一看使的時侯 //就已經被設定為內定選項了. 重新編譯程式碼以後,就可以看出.這時侯 RadioButton1 前面已經被選中了. 選擇按鈕,重要就在於選擇.現在我們來增加另外一組 RadioButton 就可以很簡潔的看出 setChecked 的作用了. 在您的 form1.h 文件中,加入: QRadioButton* RadioButton2; 在 form1.cpp 文件中加入: RadioButton2=new QRadioButton2(this,"RadioButton2"); RadioButton2->setGeometry(QRect(260, 140, 151, 61)); //這裡的位置比 RadioButton1的位置低出 //80 來. 這時侯我們重新編譯後,執行程式,就會發現. RadioButton1 前面是被自動選擇上了.而 RadioButton2 則 沒有. 因為 RadioButton 常常被用作二選一,三選一或者多選一.所以這裡向大家簡單的介紹一下ButtonGroup. 在 QT Designer 中,上面那一堆小按鈕中有一個是 ButtonGroup 的按鈕.現在在這個上面用 mouse click 一下.然後在 QT Designer 中畫出一個方的範圍來. 這個範圍要把剛剛我們畫的那個 RadioButton 包進去 喔.一定要. (see figure 2)
figure 2
回來檢查 uic 生成的 source code. 我們會發現 form1.h 中多出了 class QButtonGroup; // 用到 QButtonGroup QButtonGroup* ButtonGroup1; // QButtonGroup *ButtonGroup1 而在 form1.cpp 中,有了 #include <qbuttongroup.h> // QButtonGroup 需要的 .h 文件 ButtonGroup1 = new QButtonGroup( this, "ButtonGroup1" ); //在主視窗中生成 ButtonGroup1 ButtonGroup1->setGeometry( QRect( 230, 40, 251, 181 ) ); // 設定ButtonGroup的位置與大小 ButtonGroup1->setTitle( tr( "ButtonGroup1" ) ); //設定顯示為 "ButtonGroup1" RadioButton1 = new QRadioButton( ButtonGroup1, "RadioButton1" ); //在這裡,我們看到,這次不再是 //RadioButton1 = new QRadioButton( this, "RadioButton1" ); //而是把 this 換成了 ButtonGroup1 了.這也就是說,這次我們 //生成的 RadioButton1 是在 ButtonGroup1 這個介面上,而不是 //以前的主視窗了. RadioButton1->setGeometry( QRect( 30, 30, 151, 61 ) ); // RadioButton1 的位置也有了改變. 這裡的 30, 30 是以 ButtonGroup1 來 // 作為標準的.而不事主視窗. // 下面這兩行就不用多說了,大家一定知道 RadioButton1->setText( tr( "RadioButton1" ) ); RadioButton1->setChecked( TRUE ); 現在我們自己把上面的程式碼加入到我們的 form1.h 和 form1.cpp 中.同時把我們的 RadioButton1 從 this 改到 ButtonGroup1 位置也改變為 RadioButton1->setGeometry( QRect(30,30,151,61)); 同時更該 RadioButton2 的設定. this 改成 ButtonGroup1 位置改成 RadioButton2->setGeometry( QRect(30, 100, 151, 61)); 使 RadioButton2 跟 RadioButton1 的位置一樣,但是低 70 重新編譯程式.您就會發現這時侯的 RadioButton 變成二選一了.兩個 中您只能選擇一個.當您在 RadioButton2 前面用 mouse 按一下, RadioButton1 前面就會自動清除掉. ˇ RadioButton 通常是用在唯一選擇中.也就是說從多個選擇中,選出一個來.所以通常配合ButtonGroup 來使用.但也可以單個獨立使用. CheckBox: CheckBox 是一種跟 RadioButton 差不多的東西.通常的區別在於 CheckBox 被用於多重選擇. CheckBox 在 QT Designer 中是一個方方的中間有個 X 的標誌的東西.好像一個小箱子一樣.我們現在好像 RadioButton 一樣,做出兩個 Checkbox, 然後在做出一個 ButtonGroup.把 checkbox 2 設定為 checked form1.h 文件中,多出了 class QCheckBox; 和 QButtonGroup* ButtonGroup2; QCheckBox* CheckBox1; QCheckBox* CheckBox2; 而 form1.cpp 呢.也就有了 #include <qcheckbox.h> ButtonGroup2 = new QButtonGroup( this, "ButtonGroup2" ); ButtonGroup2->setGeometry( QRect( 20, 180, 161, 141 ) ); ButtonGroup2->setTitle( tr( "ButtonGroup2" ) ); CheckBox1 = new QCheckBox( ButtonGroup2, "CheckBox1" ); CheckBox1->setGeometry( QRect( 20, 30, 121, 41 ) ); CheckBox1->setText( tr( "CheckBox1" ) ); CheckBox2 = new QCheckBox( ButtonGroup2, "CheckBox2" ); CheckBox2->setGeometry( QRect( 20, 90, 121, 41 ) ); CheckBox2->setText( tr( "CheckBox2" ) ); CheckBox2->setChecked( TRUE ); 相信上面就不用我多解釋,大家也一定明白了吧.實際上 CheckBox 跟 RadioButton 是一種非常類似的東西. LineEdit--進入文字的處理 QT Designer 中有一個標有 『ab』 標誌的小 Icon, 那就是 LineEdit 了. 現在我們在這裡按一下,然後畫出一個 LineEdit 來. 然後在這個 LineEdit 上面,用 mouse double click. 在出現的 window 中輸入 "Display Some Text" 現在我們來看看程式碼的變化: form1.h 中,定義了 LineEdit1 class QLineEdit; QLineEdit* LineEdit1; form1.cpp 中: #include <qlineedit.h> LineEdit1 = new QLineEdit( this, "LineEdit1" ); \\生成 LineEdit1 LineEdit1->setGeometry( QRect( 130, 70, 251, 71 ) ); \\設定 LineEdit1 的位置 LineEdit1->setText( tr( "Display Some Text" ) ); \\ LineEdit1 顯示的字為 "Display Some Text" 我們可以看到,在 QT Designer 的 Property Edit 中,有一個 echoMode 的選項.現在我們把他選擇為 Password. 這時侯我們就看到剛剛打入的 "Display Some Text" 這幾個字,已經變成了 "*******"了. 在 QT Designer 中,您可以選擇 echoMode 為 Password 或者是 NoEcho. 這些通常都是用作密碼輸入 用的.當客戶輸入一組密碼的時侯,屏幕上的密碼輸入 window 並不顯示用戶的密碼明文. 而是採用 Password ---"*******" 或者 NoEcho ----(什麼都不顯示) 來代議. form1.cpp 的程式碼中會有下面的程式碼出現: LineEdit1->setEchoMode( QLineEdit::Password ); ˇ LineEdit 通常是用來顯示或者讀取單行的數據. MultiLineEdit--進一步學習文字處理 MultiLineEdit 也是作為文字處理用的.但是他的功能就比 LineEdit 要強出很多了. MultiLineEdit 的 Icon 是一個上面畫有 『cde』下面畫有 『ab』的圖案的按鈕. 我們先做出一個MultiLineEdit,然後 double click, 在文字部份寫入: This is a Multi Line Edit. we are trying to put some text here. :-) 然後觀察程式碼: form1.h 多了 class QMultiLineEdit; 和 QMultiLineEdit* MutiLineEdit1; form1.cpp中有了 #include <qmultilineedit.h> MultiLineEdit1 = new QMultiLineEdit( this, "MultiLineEdit1" ); MultiLineEdit1->setGeometry( QRect( 70, 40, 441, 281 ) ); MultiLineEdit1->setText( tr( "This is a Multi Line Edit.\n" "We are trying to put some text here.\n" ":-)" ) ); 這裡不難看出.除了 MultiLineEdit 中的 setText 可以顯示多行文字以外. 其他的東西跟 LineEdit 並沒有什麼差別. 在 MultiLineEdit 中,我們還能選擇些其他的選項. 常用的有, WordWrap, UndoDepth, ReadOnly, overWriteMode. 現在我們把 這些全都在 Property Edit 中選擇出來. WordWarp 選擇為 NoWarp UndoDepth 設定到 255 ReadOnly 為 FALSE overWriteMode 為 TRUE 這時侯 form1.cpp 中就有了下面這些新的程式碼: MultiLineEdit1->setWordWrap( QMultiLineEdit::NoWrap ); //設定我們的 MultiLineEdit1 不支援自動斷行 MultiLineEdit1->setUndoDepth( 255 ); //設定在這個 MultiLineEdit1 中所輸入的數據可以通過 mouse 的 undo 或者鍵盤的 ctrl + z //來進行復原(undo)可以復原(undo)的次數為 255 次 MultiLineEdit1->setReadOnly( FALSE ); //設定 MultiLineEdit1 可以接受客戶端的文字輸入.如果這裡為 TRUE ,那麼使用者 //就沒有辦法在這個 MultiLineEdit 輸入任何的東西了.通常只有在 MutilLineEdit //被當作純粹的文字顯示部件才會用到. MultiLineEdit1->setProperty( "overWriteMode", QVariant( TRUE, 0 ) ); //打開 overWrite 的開關.也就是說用戶輸入的時侯,會把 MultiLineEdit1 中 //本身的東西 overWrite 掉. (覆蓋寫掉) ˇ MultiLineEdit 的應用非常的廣泛.小到文字的顯示,輸入.大到文字的處理.好比 Kdevelop 中 的主 window, 我們大家寫程式的時侯,就是在一個 MultiLineEdit 中. Kdevelop 2.x 中,那種在 error code (make 時產生的)上面 double click, 然後上面就會自動 focus 到錯誤程式那行的程式.也是用 MultiLineEdit 來運作的.又例如 double click 在一段文字上面,然後 popup 新的 window 出來等等. 所以說, MultiLineEdit 真的是很重要很多用的一個物件. LCD Number--數字的顯示 在 QT Designer 中有一個畫了個數字 『42』的 Icon. 在那理點一下.就可以做出一個 LCD Number 了. 同樣的道理, form1.h 中有了 QLCDNumber 的 class, 也多出了QLCDNumber* LCDNumber1, 而 form1.cpp 中就多出了 <qlcdnumber.h> LCDNumber1 = new QLCDNumber( this, "LCDNumber1" ); LCDNumber1->setGeometry( QRect( 350, 280, 111, 81 ) ); 這樣的一個 LCDNumber 實際上還是沒有什麼作用.現在讓我們回到 QT Designer 中. 在 Property Edit 裡面給我們的 LCD 一些 value 再來看看.我們選擇numDigits 為 2, intValue 為 10.這時侯,我們來看看. form1.cpp 中有了: LCDNumber1->setNumDigits( 2 ); //最多顯示兩個數字.也就是說可以選擇從 0 到 99 LCDNumber1->setProperty( "intValue", 3 ); //最初的起始值為 3 在 QT Designer 中 LCDNumber 的 Property Edit 還有個 mode 可以用來選擇. 我們可以選擇 Hex, Dec, OCT, Bin 這四種模式. 我們現在選擇 HEX,然後就會發 現,在 form1.cpp 中有下面的程式碼: LCDNumber1->setMode( QLCDNumber::HEX ); setMode 是用來控制顯示方式的. 所以說,QT 這裡給我們提共的顯示方式有: DEC->10進位方式 HEX->16進位方式 OCT->8 進位方式 BIN->2 進位方式 在這裡,10 進位方式和16進位方式是我們常常會用到的. 5. 最後的程式 現在我們來把上面的東西結合起來,寫一個小小的程式.程式本身什麼也不做. 只是給大家介紹一下程式的入門罷了: (see figure 3)
figure 3
main.cpp 很簡單,這裡我就不多講了 //main.cpp #include "final.h" //我們後面定義的 .h 文件 #include <kapp.h> int main(int argc, char **argv) { KApplication app(argc, argv, "Form1"); Final *final=new Final(); // 後面的 final.h 會有定義 final->show(); app.setMainWidget(final); return(app.exec()); } //final.h #ifndef FINAL_H #define FINAL_H #include <qdialog.h> class QButtonGroup; //我們要用的 ButtonGroup class QCheckBox; //我們要用的 CheckBox class QGroupBox; //我們要用的 GroupBox class QLCDNumber; //我們要用的 LCDNumber class QLabel; //我們要用的 Label class QLineEdit; //我們要用的 LineEdit class QMultiLineEdit;//我們要用的 MultiLineEdit class QPushButton; //我們要用的 PushButton class QRadioButton; //我們要用的 RadioButton class QString; //MultiLineEdit 要用到的 String class Final:public QDialog //Final 基於 QDialog { Q_OBJECT public: Final (QWidget * parent = 0, const char *name = 0); //我們的主程式 ~Final (); QButtonGroup *group_one; QRadioButton *radio_two; QRadioButton *radio_one; // 第一個 ButtonGroup, 帶兩個 RadioButton (radio_two, radio_one) QGroupBox *group_two; QCheckBox *check_one; QCheckBox *check_two; QCheckBox *check_three; // GroupBox, 飽含三個 CheckBox (check_one, check_two, check_three) QPushButton *ok_one; QPushButton *ok_two; // 兩個 Pushbutton (ok_one, ok_two) 這是給 radiobutton 和 checkbutton用的 QLabel *click_label; //顯示在 LCD 上面的文字 QLabel *picture; //企鵝的圖形 QLineEdit *LineEdit; //用來顯示 radio button 的狀態 QMultiLineEdit *MultiLineEdit; //用來顯示 check box 的狀態 QLCDNumber *LCD; // 數字顯示.用來顯示 radio button 和 check box 後面的 ok 被按下去的次數. QPushButton *exit_button; // 退出程式 QPushButton *clear_button; // 清除全去選項 QButtonGroup *group_three; QRadioButton *dec; QRadioButton *oct; QRadioButton *bin; QRadioButton *hex; QPushButton *lcd_ok_button; // 另外的一個 ButtonGroup,包括了 RadioButton dec, oct, bin, hex 和 push button lcd_ok_button // 這個是用來選擇 LCD 的選擇方式的 QString CHECK; // MultlLineEdit 在顯示 check box 狀態時,需要的一個 string int i; // 我們的 LCD 用來統計數字用的 private slots: void check_radio (); //檢查 radio button 狀態的 slot void check_box (); // 檢查 check box 狀態的 slot void check_lcd (); // 檢查 LCD 顯示狀態的 slot void CLEAR (); // 清除所有選擇,回覆到程式開始原狀的 slot }; #endif // 結束了 //final.cpp #include "final.h" #include <kapp.h> // exit_button 需要用到 quit 來退出 kapplication #include <qbuttongroup.h> // buttongroup 用到 #include <qcheckbox.h> // checkbox 用到 #include &l;qgroupbox.h> // groupbox 用到 #include <qlabel.h> // label 用到 #include <qlcdnumber.h> // LCD 用到 #include <qlineedit.h> // lineedit 用到 #include <qmultilineedit.h>// multilineedit 用到 #include <qpushbutton.h> // pushbutton 用到 #include <qradiobutton.h> // radiobutton 用到 #include <qvariant.h> // LCD 用到 #include <qpixmap.h> // 圖像 (企鵝) 用到 #include <qstring.h> // multilineedit 用來顯示 check_box 狀態的 string 用到 Final::Final (QWidget * parent, const char *name): //主程式開始了 QDialog (parent, name) { if (!name) setName ("Final"); resize (596, 480); setCaption (tr ("Final")); //命名為 Final i = 0; //計數器最開始的值是 0 group_one = new QButtonGroup (this, "group_one"); group_one->setGeometry (QRect (0, 0, 110, 121)); group_one->setTitle (tr ("Group")); radio_one = new QRadioButton (group_one, "radio_one"); radio_one->setGeometry (QRect (10, 20, 90, 40)); radio_one->setText (tr ("One")); radio_one->setChecked (TRUE); radio_two = new QRadioButton (group_one, "radio_two"); radio_two->setGeometry (QRect (10, 70, 90, 40)); radio_two->setText (tr ("Two")); // 設定第一個 buttongroup, 並且在 buttongroup 上面設定 radio button 1 和 radio button 2 // radio_one 的 default 是 checked (已經被選擇的) group_two = new QGroupBox (this, "group_two"); group_two->setGeometry (QRect (0, 120, 111, 201)); group_two->setTitle (tr ("Group 2")); check_one = new QCheckBox (group_two, "check_one"); check_one->setGeometry (QRect (10, 20, 90, 40)); check_one->setText (tr ("One")); check_one->setChecked (TRUE); check_two = new QCheckBox (group_two, "check_two"); check_two->setGeometry (QRect (10, 80, 90, 40)); check_two->setText (tr ("Two")); check_three = new QCheckBox (group_two, "check_three"); check_three->setGeometry (QRect (10, 140, 90, 40)); check_three->setText (tr ("Three")); // 第二個 group 我們改用 groupbox 來作範例. 並且在 group box 上面 // 生成三個 check box , check box 1, check box 2 和 check box 3 // check_one 的 default 是 checked (已經被選擇的) ok_one = new QPushButton (this, "ok_one"); ok_one->setGeometry (QRect (120, 30, 71, 61)); ok_one->setText (tr ("OK")); // 第一個 ok button, 我們用來檢查 radio button 的狀態 ok_two = new QPushButton (this, "ok_two"); ok_two->setGeometry (QRect (120, 190, 71, 61)); ok_two->setText (tr ("OK")); // 第二個 ok button, 用來檢查 check box 的狀態 click_label = new QLabel (this, "click_label"); click_label->setGeometry (QRect (250, 270, 190, 41)); QFont click_label_font (click_label->font ()); click_label_font.setPointSize (18); click_label->setFont (click_label_font); click_label->setText (tr ("Click On OK")); click_label->setAlignment (int (QLabel::AlignCenter)); // 在 LCD 的數字上方顯示一些字. 這裡我們顯示的是 Click On Ok // 也就是說, LCD 是顯示的 ok button 被 mouse clicked 過的次數. // 這裡我們只顯示 ok_one 和 ok_two, 簡單的來說,就是顯示 radio button // 和 check box 的狀態一共被檢查過幾次 picture = new QLabel (this, "picture"); picture->setGeometry (QRect (480, 10, 110, 140)); picture->setText (tr ("Picture")); QPixmap pixmap ("logo.xpm"); picture->setPixmap (pixmap); picture->setScaledContents (TRUE); // 我用 convert 這隻程式,把那個企鵝的 logo (logo.gif) 轉換成了 logo.xpm // 這裡我們把這個 loggo 讀進來. 並且讓 picture 這個 QLabel 作為我們的顯示 // 對象. 這樣我們的程式裡面就有了一隻象徵 Linix 的小企鵝了. LineEdit = new QLineEdit (this, "LineEdit"); LineEdit->setGeometry (QRect (210, 30, 251, 51)); LineEdit->setReadOnly (TRUE); // 我們這裡用 lineedit 用來顯示 radio button // 所以我們把 LineEdit 設定為 setReadOnly (TRUE) 只讀 MultiLineEdit = new QMultiLineEdit (this, "MultiLineEdit"); MultiLineEdit->setGeometry (QRect (210, 150, 250, 90)); MultiLineEdit->setReadOnly (TRUE); // 我們用 MultiLineEdit 來顯示 check box 的狀態 // 同樣的道理,這裡我們也不需要輸入,所以設定 MultiLineEdit 為只讀 LCD = new QLCDNumber (this, "LCD"); LCD->setGeometry (QRect (220, 320, 231, 91)); LCD->setNumDigits (10); LCD->setProperty ("intValue", 0); // 因為考慮到我們會使用 bin (二進位)的方法來顯示 // 所以把顯示的最大位設置為 10 位 LCD->setNumDigits (10) // 並且設定初始值為 0 // LCDNumber 的內定顯示是 DEC 的. (十進位) group_three = new QButtonGroup (this, "group_three"); group_three->setGeometry (QRect (470, 170, 111, 221)); group_three->setTitle (tr ("LCD")); dec = new QRadioButton (group_three, "dec"); dec->setGeometry (QRect (10, 60, 81, 21)); dec->setText (tr ("Dec")); dec->setChecked (TRUE); oct = new QRadioButton (group_three, "oct"); oct->setGeometry (QRect (10, 90, 81, 31)); oct->setText (tr ("OTC")); bin = new QRadioButton (group_three, "bin"); bin->setGeometry (QRect (10, 120, 91, 31)); bin->setText (tr ("Bin")); hex = new QRadioButton (group_three, "hex"); hex->setGeometry (QRect (10, 30, 81, 21)); hex->setText (tr ("Hex")); lcd_ok_button = new QPushButton (group_three, "lcd_ok_button"); lcd_ok_button->setGeometry (QRect (10, 160, 91, 51)); lcd_ok_button->setText (tr ("OK")); // 在 LCD 旁邊再建立一個 group ( Button Group ) 裡面包含了 radio button 和 bush button // radio button 有 dec, oct, bin, hex 這四項. 用來選擇 LCD 的顯示模式 (8進位,10進位,16進位,2進位) // lcd_ok_button 是一個 push button. 最為選擇 LCD 顯示模式的 『確定』鍵 clear_button = new QPushButton (this, "cler_button"); clear_button->setGeometry (QRect (10, 420, 131, 41)); clear_button->setText (tr ("Clear All")); // 這個顯示為 clear all 的 push button, 用來把 // 所有的值都設定到原始狀態 exit_button = new QPushButton (this, "exit_button"); exit_button->setGeometry (QRect (430, 420, 131, 41)); exit_button->setText (tr ("Exit")); // 退出程式用的 push button connect (ok_one, SIGNAL (clicked ()), this, SLOT (check_radio ())); // 連接一個信號,如果 ok_one 被 click 了,就去執行 check_radio() connect (ok_two, SIGNAL (clicked ()), this, SLOT (check_box ())); // 連接一個信號,如果 ok_two 被 click 了, 就去執行 check_box() connect (lcd_ok_button, SIGNAL (clicked ()), this, SLOT (check_lcd ())); // 連接一個信號,如果 lcd_ok_button 被 click 了,就去執行 check_lcd() connect (clear_button, SIGNAL (clicked ()), this, SLOT (CLEAR ())); // 連接一個信號,如果 clear_button 被 click 了,就去執行 CLEAR () connect (exit_button, SIGNAL (clicked ()), kapp, SLOT (quit ())); // 連接一個信號,如果 exit_button 被 click 了, 就把我們的整個程式關閉掉 } Final::~Final () // { } void Final::check_radio () { i++; if (radio_one->isChecked ()) LineEdit->setText (tr ("Radio Button 1 is Checked")); if (radio_two->isChecked ()) LineEdit->setText (tr ("Radio Button 2 is Checked")); LCD->display (i); } // 在 check_radio () 中.我們用 isCheck() 來檢查 radio button 的狀態 // 如果 radio button 是被選擇的,那麼 isCheck() 將會返回 TRUE // 如果 radio button 沒有被選擇,則返回 FALSE 的值 // 如果說 radio_one 有被選擇,我們就用 setText() 在 LineEdit 中顯示 Radio Button 1 is Clicked // 這幾個字 // 如果 radio_two 有被選擇,我們就用 setText() 在 LineEdit 中顯示 Radio Button 2 is Clicked // // 在一開始,有個 i++, 這是我們用來統計 ok_one 和 ok_two 被 clicked 的次數用的 // 如果進入 check_radio() 就證明, ok_one 已經被 click 過一次.所以我們把 i+1, // 然後用 display() 在 LCD 上面顯示 i 的值 void Final::check_box () { i++; if (check_one->isChecked ()) CHECK = CHECK + "Check Box 1 is Checked\n"; if (check_two->isChecked ()) CHECK = CHECK + "Check Box 2 is Checked\n"; if (check_three->isChecked ()) CHECK = CHECK + "Check Box 3 is Checked\n"; MultiLineEdit->setText (CHECK); CHECK = ""; LCD->display (i); } // check box 這裡看上去稍稍比 radio button 複雜一些. 因為 radio button 我們只能選擇 // 一個. 要麼就是 radio_one, 要麼就是 radio_two. 所以用個 LineEdit 就可以搞定. // 但是 check box 是可以多項選擇的.也就是說既可以是 check box1 單一的被選擇. 也可以 // 是 check box 1 + check box 2, 還可以 check box 1 + check box 2 + check box 3.又或者 // check box 2 + check box 3 等等.所以這裡我們需要用到 MultiLineEdit 來顯示多行的信息. // 而信息就放在我們的 QString 中 (CHECK) // 我們用 isChecked() 來檢查 check_one, 如果 check_one 被選擇 // CHECK (我們的QString)就等於 CHECK+"Check Box 1 is Checked\n", 那麼 CHECK (QString) // 本身是空的.所以這裡 CHECK 就等於 Check Box 1 is Checked 這幾個字.後面的 \n 是 10, 也 // 就是 換行符號的意思 // 同樣的,如果 check_two 有被選擇,那麼 CHECK 就等於 CHECK+"Check Box 2 is Checked\n", // 這時侯就是兩種情況. 1. check_one 沒有被選擇,所以這時侯,我們的 String Check 就是空 // 的+"Check Box 2 is Checked\n" 這幾個字. 而如果 check_one 是有被選窄的.那麼 String // CHECK 本身已經包含了 "Check Box 1 is Checked\n"的字.這時侯在加上 "Check Box 2 is // Checked\n" 這幾個字. 那麼 String CHECK 就有兩行得內容了. // check_three 的道理跟 check_two 是一樣的. 只不過這時侯由兩種可能變成了四種而已 // 1. check_one clicked + check_two clicked // 2. check_one clicked // 3. check_two clicked // 4. check_one 和 check_two 都沒有被 click // 然後我們用 setText 把 String CHECK 顯示到我們的 MultiLineEdit 上面去. // 並且把 CHECK 中的 String 清除. (下次檢查狀態的時侯還要用到) // 因為 ok_two 被 click 過了,所以我們的 i 又加了 1, 並且在 LCD 中顯示出來 void Final::check_lcd () { if (dec->isChecked ()) { LCD->setMode (QLCDNumber::DEC); } if (hex->isChecked ()) { LCD->setMode (QLCDNumber::HEX); } if (oct->isChecked ()) { LCD->setMode (QLCDNumber::OCT); } if (bin->isChecked ()) { LCD->setMode (QLCDNumber::BIN); } } // 這是最間單的一個了 // 檢查: // dec 有被選擇, 將 LCD 顯示模式改變為 DEC // hex 有被選擇, 將 LCD 顯示模式改變為 HEX // oct 有被選擇, 將 LCD 顯示模式改變為 OCT // bin 有被選擇, 將 LCD 顯示模式改變為 BIN void Final::CLEAR () { LineEdit->clear (); MultiLineEdit->clear (); radio_one->setChecked (TRUE); dec->setChecked (TRUE); check_one->setChecked (TRUE); check_two->setChecked (FALSE); check_three->setChecked (FALSE); LCD->setMode (QLCDNumber::DEC); i = 0; LCD->setProperty ("intValue", 0); } // 這裡我們把所有選項變回程式開始的原始狀態. // 並且把顯示的狀態情況清空, LCD 設定回 0 // LineEdit->clear () 通過呼叫 clear() 把 LineEdit 清空 // MultiLineEdit->clear () 一樣的道理. 用 clear() 清空 // 用 setChecked() 來把 radio_one 設定為『已選擇』 // 用 setChecked() 把 dec 設定為 『已選擇』 // 對於 radio button 來說.比較方便.因為我們從眾多選擇中 // 只能選擇一個. 但是對於 check box 就不一樣了. check box // 可以被任意的多項選擇.所以我們只好把每一個 check box 的 // 狀態都設定一遍 // check_one->setChecked ( TRUE ) check_one 設定為『已選擇』 // check_two->setChecked ( FALSE ) check_two 設定為沒有被選擇. // check_three->setChecked ( FALSE ) check_three 設定為沒有被選擇 // LCD->setMode (QLCDNumber::DEC) 把 LCD 的顯示模式設定為 10 進位 // i=0; 把 LCD 的計數器設定為 0 // LCD->setProperty ("intVale", 0); 將 LCD 初始化,初始值為 0 大家編譯程式後,可以自己跑跑看.也可以將我們前面有說到的一些功能 自行增加進去. 例如 tooltip; PushButton 中的 setEnabled; QFont 等等. 6. 後記 其實 QT 所提共得功能遠遠不只我上面所介紹的那麼一點點.這篇文章只是 讓沒有用過 QT 的人,能對 QT 有一個簡單的概念.邁出走向 QT 的第一步. QT Designer 只是一個輔助工具.能幫助大家快速的建立一個 QT 的概念.但是 真正要學 QT 的話. 還是建議各位讀者能好好的打好基礎.(C++)自己慢慢的 一點點學起. 在您的電腦中, 安裝 QT 的時侯,有安裝一個 Online Reference 的文件. 通常在您的 $QTDIR/doc/html 中.您可以用自己喜愛的 web browser 來查看那些文件.真正有用的東西,都全都在那裡面! PS. 唉,說好聽些是說我只寫寫簡單的入門介紹.讓大家有個低門檻可以過.所以 只寫點皮毛.說實話是,昨天公司突然有事情要我忙.現在又給忙上班了.真的是 沒有時間來寫.只好快快的結束.對不起大家了.所以從 LineEdit 開始,就是在 趕時間了. 最後那個 final.cpp 還好是我前兩天先寫好的.不然可能也就省掉 了.有問題的話,來問我就好啦. ruili@worldnet.att.net