- Custom Signal & Slot
- 除了使用Qt現有元件預先定義好的Signal與Slot之外,也可以定義自己物件的Signal與Slot,方式是繼承QObject或它的子類別(例如QWidget)。
- 現在改以定義一個物件,當拉桿拉動時,必須通知該物件儲存拉桿的游標值,而物件儲存的游標值有變動時,LCD數字顯示也必須更新,這樣的一個物件不是圖形元件,它是個資料模型,用以儲存與圖形介面無關的資料。
定義一個Model Class如下:
Model.h
#ifndef MODEL_H #define MODEL_H #include <QObject> class Model : public QObject { Q_OBJECT public: Model() { m_value = 0; } int value() const { return m_value; } public slots: void setValue(int); signals: void valueChanged(int); private: int m_value; }; #endif
- 簡介Qt的Meta-Object System,它基於以下三個部份:
- QObject類別
- Q_OBJECT巨集
- Meta-Object Compiler(moc)
Qt管理的物件必須繼承QObject類別,以提供Qt物件的Meta訊息,若要實作Signal與Slot機制,則必須包括Q_OBJECT巨集,moc會處理Qt的C++擴充(Meta-Object System),使用moc讀取C++標頭檔案,若發現類別定義中包括Q_OBJECT巨集,就會產生Qt meta-object相關的C++程式碼。
若使用qmake來產生Makefile,若必要時,檔案中就會包括moc的使用,程式完成建置之後,會在release或debug目錄中,找到moc_Model.cpp,即為moc所提供的C++程式碼。
public slots:
void setValue(int);
signals:
void valueChanged(int);
在Model中,自訂了Signal與Slot,slots與signals關鍵字其實是巨集,將被展開為相關的程式碼。
Slot:定義setValue(int),將接收Signal傳來的整數資料,如果不想接受資料的話,int可以省去。
Signal:定義valueChanged(int),表示將發出的Signal會帶有一個整數。
Model.cpp
#include "Model.h" void Model::setValue(int value) { if (value != m_value) { m_value = value; emit valueChanged(m_value); } }
Slot只是一般的函式,可以由程式的其它部份直接呼叫,也可以連接至Signal,若有呼叫setValue(),程式執行到emit時,就會發出valueChanged()的Signal。
main.cpp
#include <QApplication> #include <QWidget> #include <QSlider> #include <QLCDNumber> #include "Model.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget *parent = new QWidget; parent->setWindowTitle("Signal & Slot"); parent->setMinimumSize(240, 140); parent->setMaximumSize(240, 140); QLCDNumber *lcd = new QLCDNumber(parent); lcd->setGeometry(70, 20, 100, 30); QSlider *slider = new QSlider(Qt::Horizontal, parent); slider->setRange(0, 99); slider->setValue(0); slider->setGeometry(70, 70, 100, 30); Model model; QObject::connect(slider, SIGNAL(valueChanged(int)), &model, SLOT(setValue(int))); QObject::connect(&model, SIGNAL(valueChanged(int)), lcd, SLOT(display(int))); parent->show(); return app.exec(); }
QObject::connect(slider, SIGNAL(valueChanged(int)), &model, SLOT(setValue(int)));
QObject::connect(&model, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));
這邊使用connect()連接QSlider SIGNAL:valueChanged()及Model SLOT:setValue(),當拉動拉桿時,Model的m_value就會被設定為QSlider的游標值,Model在執行setValue()過程中會emit valueChanged() signal,由於Model SIGNAL:valueChanged()連接至QLCDNumber SLOT:display(),所以LCD顯示數字也會改變。
Signal與Slot的簽名(參數)基本上要相同,但若Signal的參數多於Slot的參數,則額外的參數會被Slot忽略。
如果要斷開Signal與Slot的連接,則使用disconnect(),例如:
QObject::disconnect(slider, SIGNAL(valueChanged(int)), &model, SLOT(setValue(int)));
本文參考自"良葛格:Qt4學習筆記"
0 意見:
張貼留言