程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> Qt學習之路(9):深入了解信號槽

Qt學習之路(9):深入了解信號槽

編輯:關於C++

槽函數和普通的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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved