.tutorials/tutorial/t5/t5.pro
這個範例展示了如何建立許多元件,並使用 signal 與 slot 來把它們連接在一起,還有如何處理改變大小。
#include <QApplication> #include <QFont> #include <QLCDNumber> #include <QPushButton> #include <QSlider> #include <QVBoxLayout> #include <QWidget> class MyWidget : public QWidget { public: MyWidget(QWidget *parent = 0); }; MyWidget::MyWidget(QWidget *parent) : QWidget(parent) { QPushButton *quit = new QPushButton(tr("Quit")); quit->setFont(QFont("Times", 18, QFont::Bold)); QLCDNumber *lcd = new QLCDNumber(2); lcd->setSegmentStyle(QLCDNumber::Filled); QSlider *slider = new QSlider(Qt::Horizontal); slider->setRange(0, 99); slider->setValue(0); connect(quit, SIGNAL(clicked()), qApp, SLOT(quit())); connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int))); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(quit); layout->addWidget(lcd); layout->addWidget(slider); setLayout(layout); } int main(int argc, char *argv[]) { QApplication app(argc, argv); MyWidget widget; widget.show(); return app.exec(); }
Line by Line Walkthrough
class MyWidget : public QWidget { public: MyWidget(QWidget *parent = 0); }; MyWidget::MyWidget(QWidget *parent) : QWidget(parent) { QPushButton *quit = new QPushButton(tr("Quit")); quit->setFont(QFont("Times", 18, QFont::Bold)); QLCDNumber *lcd = new QLCDNumber(2); lcd->setSegmentStyle(QLCDNumber::Filled);
lcd 是一個 QLCDNumber,一個以類似 LCD 方式顯示數字的元件。在這個例子中被設定成顯示兩位數。我們將 QLCDNumber::segmentStyle 的屬性設定為 QLCDNumber::Filled,使這個 LCD 更容易辨識。
歷史筆記:QLCDNumber 是第一個始終寫在 Qt 裡的元件,那個時候 QPainter 只支持一個原生的繪圖函式:drawLine()。使用 QLCDNumber 來顯示分數的 Tetrix 範例最初版,也是在大約這個時候被寫出來。
QSlider *slider = new QSlider(Qt::Horizontal); slider->setRange(0, 99); slider->setValue(0);
使用者可以使用 QSlider 元件去調整一定範圍內的一個整數值。這裡我們建立了一個水平式的(horizontal) QSlider,設定它的最小值為 0、最大值為 99,且它的初始值為 0。
connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));
這裡我們使用了 signal 與 slot 的方式將 slider 的 valueChanged() signal 連接到 LCD 數字的 display() slot。
無論這個 slider 的值在何時被改變,它都會藉由發出(emit) valueChanged() signal 來傳遞這個新值。因為這個 signal 被連接到 LCD 數字的 display() slot,所以當這個 signal 傳遞時,這個 slot 就會被呼叫。這兩個物件彼此都不知道對方。這就是組件程式設計(component programming)的本質。
slot 與普通的 C++ 成員函式不同,但遵循著正規的 C++ 存取規則。
QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(quit); layout->addWidget(lcd); layout->addWidget(slider); setLayout(layout);
MyWidget 現在使用了 QVBoxLayout 來管理其子元件的幾何位置。因此,我們不需要再像第四章一樣,明確指定每一個元件的螢幕座標。此外,使用一個版面配置(layout)確保在視窗改變大小時,其子元件都能跟著改變大小。現在我們使用 QBoxLayout::addWidget() 將 quit、lcd 和 slider 加入到版面配置裡。
QWidget::setLayout() 函式把這個版面配置設置在 MyWidget 中。這使得這個版面配置成為 MyWidget 的一個子元件,所以我們不需要去擔心刪除它的問題;父子關係可以確保它將會跟著 MyWidget 一起被刪除。另外,QWidget::setLayout() 將會自動重新設定版面配置中元件的父元件,使它們成為 MyWidget 的子元件。因此,我們不需要為 quit、lcd 和 slider 元件指定 this 為它們的父元件。
在 Qt 中,元件不是其他元件的子元件(例如 this),就是沒有任何父元件。一個元件可以被加入到一個版面配置中。在這種情況下,版面配置就變成需要負起管理這些元件幾何位置的責任了,不過版面配置可以不必自己去扮演父元件的角色。事實上,QWidget 的建構子需要一個作為其父元件的 QWidget 指標,而且 QLayout 也不是繼承自 QWidget。
Running the Application
這個 LCD 數字反映了你對滾動軸(slider)所做的一切,而且這個元件也成功的處理了變更大小的動作。注意到當視窗改變大小(因為它可以)時,這個 LCD 數字也會跟著改變大小,不過其他的元件仍維持原樣(不然它們看起來會很奇怪)。
Exercises
試著改變 LCD 數字,增加更多位數或是改變模式(QLCDNumber::setMode())。你甚至可以增加四個按鈕去設定基數(number base)。
你也可以改變滾動軸的範圍。
也許使用 QSpinBox 會比使用滾動軸來的好?
試著讓應用程式在 LCD 數字溢出(overflow)時退出。
來源:Qt Tutorial 5 - Building Blocks
版本:4.4.3
4 回覆:
大大你真厲害,解釋很詳細,我有幾個問題還是不太瞭解,可以麻煩你解釋一下嘛^^ 多謝
1. QLCDNumber *lcd = new QLCDNumber(2);
這個為啥要設成2阿? 我有試過1跟3,1不能用,3卻能,這是為啥?
2.
connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
跟之前的
QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit()));
有啥差別?
3.請問大大是從哪裡學習的,哈,因為我也有興趣學,麻煩大大了,多謝。
你好,這篇文章是 Qt 的官方文件,不是我寫的
我只是將它翻譯成中文而已:)
1.
這裡的 QLCDNumber 建構子引數設為 2,是代表這個 LCD 數字為兩位數
http://doc.trolltech.com/4.6/qlcdnumber.html#QLCDNumber-2
設為 1 不能用,大概是因為超出一位數字的顯示範圍吧
2.
其實兩者是一樣的
因為範例自訂的 MyWidget 類別是 QWidget 的子類別,而 QWidget 又是 QObject 的子類別
所以在這個範例中的 MyWidget 內部呼叫 connect() 方法,等同於呼叫 QObject 的 connect() 方法
3.
其實我 Qt 不算學得很深XD
要學的話,其實官方文件都有相當詳細的說明跟範例
個人覺得算是相當不錯,你可以試著看一看:
http://doc.trolltech.com/4.6/index.html
嗯嗯 感謝大大的幫忙
在此敬上一鞠躬^^
為何connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));要加&符號
跟之前的
QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit()));卻不用加&
張貼留言