槽函數和普通的C++成員函數沒有很大的區別。它們也可以使virtual的;可以被重寫;可以使public、protected或者 private的;可以由其它的C++函數調用;參數可以是任何類型的。如果要說區別,那就是,槽函數可以和一個信號相連接,當這個信號發生時,它可以被自動調用。
connect()語句的原型類似於:
connect(sender, SIGNAL(signal), receiver, SLOT(slot));
這裡,sender和receiver都是QObject類型的,singal和slot都是沒有參數名稱的函數簽名。SINGAL()和SLOT()宏用於把參數轉換成字符串。
深入的說,信號槽還有更多可能的用法,如下所示。
一個信號可以和多個槽相連:
connect(slider, SIGNAL(valueChanged(int)),
spinBox, SLOT(setValue(int)));
connect(slider, SIGNAL(valueChanged(int)),
this, SLOT(updateStatusBarIndicator(int)));
注意,如果是這種情況,這些槽會一個接一個的被調用,但是它們的調用順序是不確定的。
多個信號可以連接到一個槽:
connect(lcd, SIGNAL(overflow()),
this, SLOT(handleMathError()));
connect(calculator, SIGNAL(divisionByZero()),
this, SLOT(handleMathError()));
這是說,只要任意一個信號發出,這個槽就會被調用。
一個信號可以連接到另外的一個信號:
connect(lineEdit, SIGNAL(textChanged(const QString &)),
this, SIGNAL(updateRecord(const QString &)));
這是說,當第一個信號發出時,第二個信號被發出。除此之外,這種信號-信號的形式和信號-槽的形式沒有什麼區別。
槽可以被取消鏈接:
disconnect(lcd, SIGNAL(overflow()),
this, SLOT(handleMathError()));
這種情況並不經常出現,因為當一個對象delete之後,Qt自動取消所有連接到這個對象上面的槽。
為了正確的連接信號槽,信號和槽的參數個數、類型以及出現的順序都必須相同,例如:
connect(ftp, SIGNAL(rawCommandReply(int, const QString &)),
this, SLOT(processReply(int, const QString &)));
這裡有一種例外情況,如果信號的參數多於槽的參數,那麼這個參數之後的那些參數都會被忽略掉,例如:
connect(ftp, SIGNAL(rawCommandReply(int, const QString &)),
this, SLOT(checkErrorCode(int)));
這裡,const QString &這個參數就會被槽忽略掉。
如果信號槽的參數不相容,或者是信號或槽有一個不存在,或者在信號槽的連接中出現了參數名字,在Debug模式下編譯的時候,Qt都會很智能的給出警告。
在這之前,我們僅僅在widgets中使用到了信號槽,但是,注意到connect()函數其實是在QObject中實現的,並不局限於GUI,因此,只要我們繼承QObject類,就可以使用信號槽機制了:
class Employee : public QObject
{
Q_OBJECT
public:
Employee() { mySalary = 0; }
int salary() const { return mySalary; }
public slots:
void setSalary(int newSalary);
signals:
void salaryChanged(int newSalary);
private:
int mySalary;
};
在使用時,我們給出下面的代碼:
void Employee::setSalary(int newSalary)
{
if (newSalary != mySalary) {
mySalary = newSalary;
emit salaryChanged(mySalary);
}
}
這樣,當setSalary()調用的時候,就會發出salaryChanged()信號。注意這裡的if判斷,這是避免遞歸的方式!還記得前面提到的循環連接嗎?如果沒有if,當出現了循環連接的時候就會產生無限遞歸。
出處: http://devbean.blog.51cto.com/448512/199461