信號與槽
信號和槽是QT中最基本的概念,也是QT中的核心機制。信號和槽是QT自行定義的一種通信機制,獨立於標準的C/C++語言,因此要正確的處理信號和槽,必須藉助moc(Meta Object Compiler)這一QT工具,該工具是個C++預處理程式,它爲高層次的事件處理自動生成所需要的附加代碼。
信號與槽可以實現多信號與單個槽的連接,也可以實現單信號與多個槽的連接,甚至能實現信號間的連接,這時第一個信號發射後,第二個信號也將被即時發射。如果單信號連接多個槽,當這個信號被髮射時,與之相關的槽被激活的順序將是隨機的。
所有從QObject或其子類(例如Qwidget)派生的類都能夠包含信號和槽。當對象改動其狀態時,信號就由該對象發射(emit)出去,而槽則用於接收信號。
signals前面不可加public、private和protected進行修飾,它必須是void類型而且只聲明不定義。slots前面可以加修飾,它作爲普通的C++成員函數,能被正常調用。slots區域中的函數能有參數,但其參數不能有缺省值。 宏定義不能用在signal和slot的參數中。
1、當信號與槽函數的參數數量相同時,它們參數類型要完全一致。
// 頭文件
#include <QtWidgets/QMainWindow>
#include "ui_ImageProcessing.h"
class ImageProcessing : public QMainWindow
{
Q_OBJECT
public:
ImageProcessing(QWidget *parent = Q_NULLPTR);
private:
Ui::ImageProcessingClass ui;
signals:
void iSignal(int b); // 信號
private slots:
void iSlot(int b); // 槽函數
};
// cpp
#include <QMainWindow>
#include <QtGui>
#include <QtWidgets>
#include "MainWindow.h"
ImageProcessing::ImageProcessing(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
connect(this, SIGNAL(iSignal(int)), this, SLOT(iSlot(int))); // 連接信號和槽函數
emit iSignal(5); // 發射信號
}
void ImageProcessing::iSlot(int b) // 槽函數定義
{
QString qString;
qDebug() << qString.number(b);
}
2、當信號的參數與槽函數的參數數量不同時,只能是信號的參數數量多於槽函數的參數數量,且前面相同數量的參數類型應一致,信號中多餘的參數會被忽略。
// 頭文件
#include <QtWidgets/QMainWindow>
#include "ui_ImageProcessing.h"
class ImageProcessing : public QMainWindow
{
Q_OBJECT
public:
ImageProcessing(QWidget *parent = Q_NULLPTR);
private:
Ui::ImageProcessingClass ui;
signals:
void iSignal(int a,float b); // 信號
private slots:
void iSlot(int b); // 槽函數
};
// cpp
#include <QMainWindow>
#include <QtGui>
#include <QtWidgets>
#include "MainWindow.h"
ImageProcessing::ImageProcessing(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
connect(this, SIGNAL(iSignal(int,float)), this, SLOT(iSlot(int))); // 連接信號和槽函數
emit iSignal(1000, 0.3); // 發射信號
}
void ImageProcessing::iSlot(int b) // 槽函數定義
{
QString qString;
qDebug() << qString.number(b);
}
3、在不進行參數傳遞時,信號槽綁定時也是要求信號的參數數量大於等於槽函數的參數數量。這種情況一般是一個帶參數的信號去綁定一個無參數的槽函數。
// 頭文件
#include <QtWidgets/QMainWindow>
#include "ui_ImageProcessing.h"
class ImageProcessing : public QMainWindow
{
Q_OBJECT
public:
ImageProcessing(QWidget *parent = Q_NULLPTR);
private:
Ui::ImageProcessingClass ui;
signals:
void iSignal(int a,float b);
private slots:
void iSlot();
};
// cpp
#include <QMainWindow>
#include <QtGui>
#include <QtWidgets>
#include "MainWindow.h"
ImageProcessing::ImageProcessing(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
connect(this, SIGNAL(iSignal(int,float)), this, SLOT(iSlot()));
emit iSignal(1000, 0.3);
}
void ImageProcessing::iSlot()
{
QString qString = " Qt test (signals & slots) ";
qDebug() << qString;
}
斷開連接
當信號與槽沒有必要繼續保持關聯時,我們可以使用 disconnect 函數來斷開連接。其定義如下,用於斷開發射者中的信號與接收者中的槽函數之間的關聯。
bool QObject::disconnect(const QObject * sender, const char * signal, const Object * receiver, const char * member)
有三種情況必須使用 disconnect() 函數:
1、斷開與某個對象相關聯的任何對象。
在某個對象中可能定義了一個或者多個信號時,這些信號與另外若干個對象中的槽相關聯,如果我們要切斷這些關聯,就可以利用這個方法,簡潔有效。
disconnect(myObject, 0, 0, 0)
// myObject->disconnect()
2、斷開與某個特定信號的任何關聯。
disconnect(myObject, SIGNAL(mySignal()), 0, 0)
// myObject->disconnect(SIGNAL(mySignal()))
3、斷開兩個對象之間的關聯。
disconnect(myObject, 0, myReceiver, 0)
// myObject->disconnect(myReceiver)
在 disconnect 函數中 0 可以用作一個通配符,分別表示任何信號、任何接收對象、接收對象中的任何槽函數。但是發射者 sender 不能爲 0,其它三個參數的值可以等於 0。