快快樂樂學 QT - 第一章 Getting Started (2)

Making Connections

在下一個例子當中,將會告訴我們如何對使用者的動作做出回應。這個程式包含了一個按鈕,當使用者點了這個按鈕之後,程式就會離開。這個程式跟 Hello 這隻相當類似,主要差別在於我們用 QPushButton 來代替 QLabel以下是範例:
1  #include <qapplication.h>
2  #include <qpushbutton.h>

3  int main( int argc, char *argv[] )
4  {
5      QApplication app(argc, argv) ;
6      QPushButton *button = new QPushButton("Quit", 0) ;
7      QObject::connect(button, SIGNAL( clicked() ),
8                               &app, SLOT( quit() )) ;
9      app.setMainWidget(button) ;
10     button->show() ;
11     return app.exec() ;
12 }

QT 的 widget 透過 signals 表示使用者的動作或者是狀態的改變。舉例來說,QPushButton會在使用者按下按鈕的時候,發出一個 clicked() signal。Signal 可以跟 function 作連結(接下來這個 function 我們會稱作 slot),也就是說,當一個 signal 被發出的時候,slot 就會自動的被執行。

在我們的例子當中,我們把按鈕的 clicked() signal 跟 QApplication 物件的 quit() slot 做了連結,SIGNAL() 以及 SLOT() 這兩個 macros 是 Qt 語法的一部分,在下一章當中會有更詳細的解釋。

接著我們就來 build 並且執行這個程式,當程式執行之後,如果你按下了 Quit,或是按下空白鍵(代表按下 Quit 按鈕),你會發現程式會結束執行。

下一個例子則是展示了如何利用 signals 以及 slots 讓兩個 widget 同步,這個程式詢問使用者的年紀,使用者可以透過一個 spin box 或是 slider 來作輸入。 程式包含了三個 widgets:QSpinBoxQSliderQHBox (horizontal layout box)。QHBox 是程式的 main widget,QSpinBox 以及 QSlider 被放在 QHBox 裡面,它們兩個是 QHBoxchildren

1  #include <qapplication.h>
2  #include <qhbox.h>
3  #include <qslider.h>
4  #include <qspinbox.h>

5  int main( int argc, char *argv[] )
6  {
7      QApplication app(argc,argv) ;
8      QHBox *hbox = new QHBox(0) ;
9      hbox->setCaption("Enter Your Age") ;
10     hbox->setMargin(6) ;
11     hbox->setSpacing(6) ;

12     QSpinBox *spinBox = new QSpinBox(hbox) ;
13     QSlider *slider = new QSlider(Qt::Horizontal, hbox) ;
14     spinBox->setRange(0,130) ;
15     slider->setRange(0,130) ;

16     QObject::connect(spinBox, SIGNAL(valueChanged(int)),
17                              slider, SLOT(setValue(int))) ;
18     QObject::connect(slider, SIGNAL(valueChanged(int)),
19                              spinBox, SLOT(setValue(int))) ;
20     spinBox->setValue(35) ;
21     app.setMainWidget(hbox);
22     hbox->show() ;
23     return app.exec() ;
24  }


第 8 行到第 11 行我們對 QHBox 做了一些設定,我們在 QHBox 的外圍以及跟 child widget 之間留了一些空間 (6 pixels)。12 和 13 行我們產生了行我們產生了 QSpinBox 以及 QSlider 物件,並且把他們兩個的 parent 都設定為 QHBox

儘管我們沒有明確設定這兩個 widget 的位置以及大小,我們仍然會發現 QSpinBox 還有 QSliderQHBox 當中躺的好好的,這是因為 QHBox 會自動的給他的 child 合理的位置還有大小。Qt 提供了許多像是 QHBox 之類的 classes 讓我們不用刻意去指定 widget 的位置以及大小。

14 以及 15 行設定了 spin box 以及 slider 的合法範圍,16 到 19 行的兩個 connect 則是讓 spin box 以及 slider 作同步的動作,使他們兩個都會有相同的值。當任何一個 widget 的值改變,就會丟出 valueChanged(int) 的 signal,連接到另外一個 widget 的 setValue(int) slot,並且跟著改變值。

第 20 行把 spin box 的值設定為 35,當跑到這一行時,QSpinBox 發出了 valueChanged(int) 的 signal,並且還有一個值為 35 的 int argument。這個 arguemnt 會被傳到 QSlidersetValue(int) slot,把 slider 的值設成 35。接著 slider 又會因為 slider 的值改變了而送出一個 valueChanged(int) 的 signal,不過在這個時候,因為 spin box 的值已經是 35 了,所以不會有 setValue(int) 的發生。這樣可以避免無窮迴圈的狀況發生。

總結一下,Qt 建造使用者介面的方法相當簡單易懂而且有彈性,並且透過 layout,我們可以不用擔心 widget 的大小還有位置問題。UI 的行為則是透過 widget 之間的 signals 還有 slots 機制來作管理。