本文連接:https://blog.csdn.net/hhhuang1991/article/details/79829784
信號和槽機制是 QT 的核心機制,要精通QT編程就必須對信號和槽有所瞭解。編程
1、使用方法
1. 爲控件添加信號和槽
手動添加
//MyDlg.h
#pragma once
#include <QtWidgets/QDialog>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QHBoxLayout>安全
class MyDlg : public QDialog
{
//只有加入了Q_OBJECT,你才能使用QT中的signal和slot機制。
Q_OBJECT
private:
QLabel* plabel;
QLineEdit* pEdit;
QPushButton* pBtn;多線程
public slots:
void Print();
public:
MyDlg(QWidget* parent = Q_NULLPTR);
};框架
//MyDlg.cpp
#include "MyDlg.h"
#include <QtWidgets/QApplication>
MyDlg::MyDlg(QWidget* parent/* = Q_NULLPTR*/) :
QDialog(parent)
{
/** @breif QT5中如何解決中文亂碼問題:
* 常量:QString::fromLocal8Bit和QStringLiteral
* 對於字符串變量,使用QString自帶函數
*/
plabel = new QLabel(QString::fromLocal8Bit("姓名"));
pEdit = new QLineEdit;
pBtn = new QPushButton(QString::fromLocal8Bit("確認"));
// 使用佈局管理器佈局控件
QHBoxLayout *Layout = new QHBoxLayout;
Layout->addWidget(plabel);
Layout->addWidget(pEdit);
QVBoxLayout* BottomLayout = new QVBoxLayout;
BottomLayout->addLayout(Layout);
BottomLayout->addWidget(pBtn);
// 設置窗口的佈局管理器
setLayout(BottomLayout);
setWindowTitle(tr("Find"));
setFixedHeight(sizeHint().height());
//信號與槽的綁定
connect(pBtn, SIGNAL(clicked()), this, SLOT(Print()));
}函數
void MyDlg::Print()
{
QMessageBox::information(this, QString::fromLocal8Bit("確認"),
QString::fromLocal8Bit("你點擊了我"), QMessageBox::Ok);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyDlg mydlg;
mydlg.show();
return a.exec();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
解析:
1. MyDlg類中必需要在一行定義Q_OBJECT這個宏,這樣才能在類中使用信號和槽的功能;
2. 在類中聲明並實現槽函數void print(), 槽函數都是聲明在public slots下,固然也能夠是private slots或protected slots,工具
//MyDlg.h
public slots:
void Print();
//MyDlg.cpp
void MyDlg::Print()
{
QMessageBox::information(this, QString::fromLocal8Bit("確認"),
QString::fromLocal8Bit("你點擊了我"), QMessageBox::Ok);
}
1
2
3
4
5
6
7
8
9
3 . 使用connect函數關聯按鈕的clicked()信號和槽函數print(),佈局
connect(pBtn, SIGNAL(clicked()), this, SLOT(Print()));
1
4.運行程序,點擊按鈕,會彈出「你點擊了我」的消息框。性能
若是將帶有Q_OBJECT宏的類聲明放在cpp文件中,編譯就會出現以下錯誤:
錯誤:1>main.obj : error LNK2001: 沒法解析的外部符號 「public: virtual struct QMetaObject const * __thiscall MyDlg::metaObject(void)const 」 (?metaObject@MyDlg@@UBEPBUQMetaObject@@XZ)
1>main.obj : error LNK2001: 沒法解析的外部符號 「public: virtual void * __thiscall MyDlg::qt_metacast(char const *)」 (?qt_metacast@MyDlg@@UAEPAXPBD@Z)
1>main.obj : error LNK2001: 沒法解析的外部符號 「public: virtual int __thiscall MyDlg::qt_metacall(enum QMetaObject::Call,int,void * *)」 (?qt_metacall@MyDlg@@UAEHW4Call@QMetaObject@@HPAPAX@Z)
1>main.obj : error LNK2001: 沒法解析的外部符號 「public: static struct QMetaObject const MyDlg::staticMetaObject」 (?staticMetaObject@MyDlg@@2UQMetaObject@@B)
緣由:只有繼承了QObject類的類,才具備信號槽的能力。因此,爲了使用信號槽,必須繼承QObject。凡是QObject類(不論是直接子類仍是間接子類),都應該在第一行代碼寫上Q_OBJECT。不論是不是使用信號槽,都應該添加這個宏。這個宏的展開將爲咱們的類提供信號槽機制、國際化機制以及 Qt 提供的不基於 C++ RTTI 的反射能力。所以,若是你以爲你的類不須要使用信號槽,就不添加這個宏,就是錯誤的。其它不少操做都會依賴於這個宏。注意,這個宏將由 moc(咱們會在後面章節中介紹 moc。這裏你能夠將其理解爲一種預處理器,是比 C++ 預處理器更早執行的預處理器。) 作特殊處理,不只僅是宏展開這麼簡單。moc 會讀取標記了 Q_OBJECT 的頭文件,生成以 moc_ 爲前綴的文件,好比 MyDlg.h 將生成 moc_MyDlg.cpp。你能夠到構建目錄查看這個文件,看看到底增長了什麼內容。注意,因爲 moc 只處理頭文件中的標記了Q_OBJECT的類聲明,不會處理 MyDlg.cpp 文件中的相似聲明。所以,若是咱們的MyDlg類位於 MyDlg.cpp 中,是沒法獲得 moc 的處理的。解決方法是,咱們仍是將其放在頭文件中。ui
Qt Designer中自動添加
打開Qt Designer,編輯界面ui文件,而後按下圖所示,添加信號槽,this
在Qt Designer編輯好後,還須要將添加的槽函數,聲明和定義到框架類中去,
public slots:
void OnPushButton()
{
QMessageBox::information(this, QString::fromLocal8Bit("確認"),
QString::fromLocal8Bit("你點擊了我"), QMessageBox::Ok);
}
1
2
3
4
5
6
這種方法就不須要採用connect去鏈接信號和槽。
2. 添加自定義信號和槽
信號和槽實現兩個對象的通信。
//sender類給recv類發送信號,receiver類接收到信號後,執行槽函數
class sender
{
Q_OBJECT
signals:
void send(); //信號只須要定義,不須要聲明
}
class receiver
{
Q_OBJECT
public slots:
void recv(){} //槽函數
}
//在主框架類的構造函數中,鏈接信號和槽
sender* psender = new sender;
receiver* precv = new receiver;
connect(psender, SIGNAL(send()), precv, SLOT(recv()));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2、特色
信號和槽是QT自行定義的一種通訊機制,它獨立於標準的 C / C++ 語言,所以要正確的處理信號和槽,必須藉助一個稱爲 moc(Meta Object Compiler)的QT工具,該工具是一個C++ 預處理程序,它爲高層次的事件處理自動生成所須要的附加代碼。全部從 QObject 或其子類(例如 Qwidget) 派生的類都可以包含信號和槽。主要有如下幾個特色:
一、類型安全。
須要關聯的信號和槽的簽名必須是等同。即信號的參數類型和參數個數 同接收該信號的槽的參數類型和參數個數相同。
2. 信息封裝。
激發信號的Qt對象無須知道是哪一個對象的哪一個槽須要接收它發出的信號,它只須要作的是在適當的時間發送適當的信號就能夠了,而不須要知道也不關心它的信號有沒有被接收到,更不須要知道哪一個對象的哪一個槽接收到了信號。一樣地,對象的槽也不知道是哪些信號關聯了本身,而一旦關聯信號和槽,Qt就保證了適合的槽獲得了調用。即便關聯的對象在運行時被刪除。應用程序也不會崩潰。
3.自由鏈接。
一個信號能夠鏈接多個槽函數,而一個槽函數也能夠鏈接多個信號,一個信號還能夠鏈接另一個信號。對於與一個信號相連的多個槽函數,他們的執行順序是隨機的。
4.效率不高。
信號和槽機制加強了對象間通訊的靈活性,然而這也損失了一些性能。同回調函數相比,信號和槽機制運行速度有些慢。一般,經過傳遞一個信號來調用槽函數將會比直接調用直接調用非虛函數運行速度慢10倍。緣由以下:
須要定位接收信號的對象。 安全地遍歷全部的關聯。 編組/解組傳遞的參數。 多線程的時候。信號可能須要排隊等待。 ———————————————— 版權聲明:本文爲CSDN博主「hhhuang1991」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接及本聲明。 原文連接:https://blog.csdn.net/hhhuang1991/article/details/79829784