星期日, 4月 01, 2007

qt signals and slots 機制

繼承了 QObject 並且在 head file 中有輸入 Q_OBJECT 的類別,再經過
MOC (Meta Object Compiler) 的處理後便具備了 Signals and Slots 的能力

什麼是 Signals and Slots?

Signals : 基本上可以把這個想成一個 event , 在特殊情況之下會被發送出去

Slots : 在 Signal 被發送出來後,就由 Slots 來接收。這個 Slots 實際上就是一個
特殊的 member function。

來自於官網的例子:

#include <QApplication>
#include <QFont>
#include <QPushbutton>

int main(int argc, char *argv[]){
QApplication app(argc, argv);
// 維護及處理 QT 程式運作的物件

QPushButton quit("Quit");
quit.resize(75, 30);
quit.setFont(QFont("Times", 18, QFont::Bold));

QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit()));
//注意此行,將 quit 所發出的 clicked() signal 與 app 的 quit slot 連接起來
//只要 quit 發出此訊號,屬於 app 的 quit slot 就會被執行起來
quit.show();
return app.exec();
//啟動 event-loop
}

在以上的程式中可以很清楚的看到怎麼連接 signal 跟 slot
要注意的是發送者不會知道誰會收到此訊號,接收者也不會知道訊號從哪裡來.

接下來看看典型的 QObject class 長怎樣

#include <QObject>

class Counter : public QObject
{
Q_OBJECT

public:
Counter() { m_value = 0; }

int value() const { return m_value; }

public slots: // QT 新增,宣告 slots 的方法
void setValue(int value);

signals: // QT 新增,宣告 signals 的方法,注意不可實做
void valueChanged(int newValue);

private:
int m_value;
};

void Counter::setValue(int value)
{
if (value != m_value) {
m_value = value;
emit valueChanged(value); // 發送 valueChanged 信號
}
}

為了支援 QT 的獨特功能,這些 head file 必須先經過 moc 處理才能丟給編譯器處理
接下來看看如何連結

Counter a, b;
QObject::connect(&a, SIGNAL(valueChanged(int)), // SIGNAL 與 SLOT 應是 QT
&b, SLOT(setValue(int))); // 中定的巨集
// 若 a 發出 valueChanged(int)
// 信號,將其送到 b 的
// setValue slot
// 注意 member function 的
// proto type , 代表其有參數
// 傳遞

a.setValue(12); // a.value() == 12, b.value() == 12
b.setValue(48); // a.value() == 12, b.value() == 48