C++框架_之Qt的信号和槽的详解
目錄
- C++_之Qt的信號(hào)和槽的詳解
- 1、概述
- 1.1對(duì)象樹(子對(duì)象動(dòng)態(tài)分配空間不需要釋放)
- 2、信號(hào)和槽
- Qt5 的書寫方式:(推薦的使用)★★★★★
- Qt4 的書寫方式:
- 3、自定義信號(hào)槽
- 3.1自定義信號(hào)槽需要注意的事項(xiàng)
- 3.2信號(hào)槽的更多用法
- 4、Lambda表達(dá)式
?
正文
回到頂部
C++_之Qt的信號(hào)和槽的詳解
回到頂部
1、概述
信號(hào)槽是 Qt 框架引以為豪的機(jī)制之一。所謂信號(hào)槽,實(shí)際就是觀察者模式。當(dāng)某個(gè)事件發(fā)生之后,比如,按鈕檢測到自己被點(diǎn)擊了一下,它就會(huì)發(fā)出一個(gè)信號(hào)(signal)。這種發(fā)出是沒有目的的,類似廣播。如果有對(duì)象對(duì)這個(gè)信號(hào)感興趣,它就會(huì)使用連接(connect)函數(shù),意思是,將想要處理的信號(hào)和自己的一個(gè)函數(shù)(稱為槽(slot))綁定來處理這個(gè)信號(hào)。也就是說,當(dāng)信號(hào)發(fā)出時(shí),被連接的槽函數(shù)會(huì)自動(dòng)被回調(diào)。這就類似觀察者模式:當(dāng)發(fā)生了感興趣的事件,某一個(gè)操作就會(huì)被自動(dòng)觸發(fā)。(這里提一句,Qt 的信號(hào)槽使用了額外的處理來實(shí)現(xiàn),并不是 GoF 經(jīng)典的觀察者模式的實(shí)現(xiàn)方式。)
信號(hào)和槽是Qt特有的信息傳輸機(jī)制,是Qt設(shè)計(jì)程序的重要基礎(chǔ),它可以讓互不干擾的對(duì)象建立一種聯(lián)系。
槽的本質(zhì)是類的成員函數(shù),其參數(shù)可以是任意類型的。和普通C++成員函數(shù)幾乎沒有區(qū)別,它可以是虛函數(shù);也可以被重載;可以是公有的、保護(hù)的、私有的、也可以被其他C++成員函數(shù)調(diào)用。唯一區(qū)別的是:槽可以與信號(hào)連接在一起,每當(dāng)和槽連接的信號(hào)被發(fā)射的時(shí)候,就會(huì)調(diào)用這個(gè)槽。
1.1對(duì)象樹(子對(duì)象動(dòng)態(tài)分配空間不需要釋放)
參考連接:https://blog.csdn.net/fzu_dianzi/article/details/6949081
?
Qt提供了一種機(jī)制,能夠自動(dòng)、有效的組織和管理繼承自QObject的Qt對(duì)象,這種機(jī)制就是對(duì)象樹。
Qt對(duì)象樹在用戶界面編程上是非常有用的。它能夠幫助程序員減輕內(nèi)存泄露的壓力。
比如說當(dāng)應(yīng)用程序創(chuàng)建了一個(gè)具有父窗口部件的對(duì)象時(shí),該對(duì)象將被加入父窗口部件的孩子列表。當(dāng)應(yīng)用程序銷毀父窗口部件時(shí),其下的孩子列表中的對(duì)象將被一一刪除。這讓我們?cè)诰幊虝r(shí),能夠?qū)⒅饕Ψ旁谙到y(tǒng)的業(yè)務(wù)上,提高編程效率,同時(shí)也保證了系統(tǒng)的穩(wěn)健性。
下面筆者將簡單分析對(duì)象樹。
代碼驗(yàn)證:
int main(int argc, char *argv[]) {QApplication app(argc, argv);QDialog *dlg = new QDialog(0);QPushButton *btn = new QPushButton(dlg);qDebug() << "dlg = " << dlg;qDebug() << "btn = " << btn;dlg->exec();delete btn;qDebug() << "dlg = " << dlg;return 0; } dlg = QDialog(0x3ea1a0) btn = QPushButton(0x3ea228) /*關(guān)閉窗口后,dlg = QDialog(0x3ea1a0) 這說明關(guān)閉窗口,不會(huì)銷毀該窗口部件,而是將其隱藏起來。 我們?cè)趒Debug() << "dlg = " << dlg; 之后加上 qDebug() << "btn = " << btn; 明顯的,我們之前已經(jīng)delete btn,btn指針沒有被賦值為0,這是編譯器決定的。 執(zhí)行程序后,必然出現(xiàn)段錯(cuò)誤。 2、 將程序稍微修改下。*/ int main(int argc, char *argv[]) {QApplication app(argc, argv);QDialog *dlg = new QDialog(0);QPushButton *btn = new QPushButton(dlg);qDebug() << "dlg = " << dlg;qDebug() << "btn = " << btn;dlg->exec();delete dlg;qDebug() << "btn = " << btn;return 0; }回到頂部
2、信號(hào)和槽
為了體驗(yàn)一下信號(hào)槽的使用,我們以一段簡單的代碼說明:
Qt5 的書寫方式:(推薦的使用)★★★★★
#include <QApplication> #include <QPushButton>int main(int argc, char *argv[]) {QApplication app(argc, argv);QPushButton button("Quit"); QObject::connect(&button, &QPushButton::clicked, &app, &QApplication::quit);button.show();return app.exec(); }我們按照前面文章中介紹的在 Qt Creator 中創(chuàng)建工程的方法創(chuàng)建好工程,然后將main()函數(shù)修改為上面的代碼。點(diǎn)擊運(yùn)行,我們會(huì)看到一個(gè)按鈕,上面有“Quit”字樣。點(diǎn)擊按鈕,程序退出。
connect()函數(shù)最常用的一般形式:
connect(sender, signal, receiver, slot);參數(shù):
?sender:發(fā)出信號(hào)的對(duì)象
?signal:發(fā)送對(duì)象發(fā)出的信號(hào)
?receiver:接收信號(hào)的對(duì)象
?slot:接收對(duì)象在接收到信號(hào)之后所需要調(diào)用的函數(shù)
信號(hào)槽要求信號(hào)和槽的參數(shù)一致,所謂一致,是參數(shù)類型一致。如果不一致,允許的情況是,槽函數(shù)的參數(shù)可以比信號(hào)的少,即便如此,槽函數(shù)存在的那些參數(shù)的順序也必須和信號(hào)的前面幾個(gè)一致起來。這是因?yàn)?#xff0c;你可以在槽函數(shù)中選擇忽略信號(hào)傳來的數(shù)據(jù)(也就是槽函數(shù)的參數(shù)比信號(hào)的少),但是不能說信號(hào)根本沒有這個(gè)數(shù)據(jù),你就要在槽函數(shù)中使用(就是槽函數(shù)的參數(shù)比信號(hào)的多,這是不允許的)。
如果信號(hào)槽不符合,或者根本找不到這個(gè)信號(hào)或者槽函數(shù),比如我們改成:
connect(&button, &QPushButton::clicked, &QApplication::quit2);由于 QApplication 沒有 quit2 這樣的函數(shù),因此在編譯時(shí)會(huì)有編譯錯(cuò)誤:
'quit2' is not a member of QApplication這樣,使用成員函數(shù)指針我們就不會(huì)擔(dān)心在編寫信號(hào)槽的時(shí)候出現(xiàn)函數(shù)錯(cuò)誤。
Qt4 的書寫方式:
int main(int argc, char *argv[]) { QApplication a(argc, argv); QPushButton *button = new QPushButton("Quit"); connect(button, SIGNAL(clicked()), &a, SLOT(quit())); button->show(); return a.exec(); }這里使用了SIGNAL和SLOT這兩個(gè)宏,將兩個(gè)函數(shù)名轉(zhuǎn)換成了字符串。注意到connect()函數(shù)的 signal 和 slot 都是接受字符串,一旦出現(xiàn)連接不成功的情況,Qt4是沒有編譯錯(cuò)誤的(因?yàn)橐磺卸际亲址?#xff0c;編譯期是不檢查字符串是否匹配),而是在運(yùn)行時(shí)給出錯(cuò)誤。這無疑會(huì)增加程序的不穩(wěn)定性。
Qt5在語法上完全兼容Qt4
小總結(jié):
1>. 格式: connect(信號(hào)發(fā)出者對(duì)象(指針), &className::clicked, 信號(hào)接收者對(duì)象(指針), &classB::slot);
2>. 標(biāo)準(zhǔn)信號(hào)槽的使用:
connect(sender, &Send::signal, receiver, &Receiver::slot)
回到頂部
3、自定義信號(hào)槽
使用connect()可以讓我們連接系統(tǒng)提供的信號(hào)和槽。但是,Qt 的信號(hào)槽機(jī)制并不僅僅是使用系統(tǒng)提供的那部分,還會(huì)允許我們自己設(shè)計(jì)自己的信號(hào)和槽。
下面我們看看使用 Qt 的信號(hào)槽,實(shí)現(xiàn)一個(gè)報(bào)紙和訂閱者的例子:
有一個(gè)報(bào)紙類Newspaper,有一個(gè)訂閱者類Subscriber。Subscriber可以訂閱Newspaper。這樣,當(dāng)Newspaper有了新的內(nèi)容的時(shí)候,Subscriber可以立即得到通知。
?
#include <QObject>// newspaper.h // class Newspaper : public QObject {Q_OBJECT public:Newspaper(const QString & name) :m_name(name){}void send(){emit newPaper(m_name);}signals:void newPaper(const QString &name);private:QString m_name; };// reader.h // #include <QObject> #include <QDebug>class Reader : public QObject {Q_OBJECT public:Reader() {}void receiveNewspaper(const QString & name){qDebug() << "Receives Newspaper: " << name;} };// main.cpp // #include <QCoreApplication>#include "newspaper.h" #include "reader.h"int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);Newspaper newspaper("Newspaper A");Reader reader;QObject::connect(&newspaper, &Newspaper::newPaper,&reader, &Reader::receiveNewspaper);newspaper.send();return app.exec(); }●首先看Newspaper這個(gè)類。這個(gè)類繼承了QObject類。只有繼承了QObject類的類,才具有信號(hào)槽的能力。所以,為了使用信號(hào)槽,必須繼承QObject。凡是QObject類(不管是直接子類還是間接子類),都應(yīng)該在第一行代碼寫上Q_OBJECT。不管是不是使用信號(hào)槽,都應(yīng)該添加這個(gè)宏。這個(gè)宏的展開將為我們的類提供信號(hào)槽機(jī)制、國際化機(jī)制以及 Qt 提供的不基于 C++ RTTI 的反射能力。
?
●?Newspaper類的 public 和 private 代碼塊都比較簡單,只不過它新加了一個(gè) signals。signals 塊所列出的,就是該類的信號(hào)。信號(hào)就是一個(gè)個(gè)的函數(shù)名,返回值是 void(因?yàn)闊o法獲得信號(hào)的返回值,所以也就無需返回任何值),參數(shù)是該類需要讓外界知道的數(shù)據(jù)。信號(hào)作為函數(shù)名,不需要在 cpp 函數(shù)中添加任何實(shí)現(xiàn)。
?
●Newspaper類的send()函數(shù)比較簡單,只有一個(gè)語句emit newPaper(m_name);。emit 是 Qt 對(duì) C++ 的擴(kuò)展,是一個(gè)關(guān)鍵字(其實(shí)也是一個(gè)宏)。emit 的含義是發(fā)出,也就是發(fā)出newPaper()信號(hào)。感興趣的接收者會(huì)關(guān)注這個(gè)信號(hào),可能還需要知道是哪份報(bào)紙發(fā)出的信號(hào)?所以,我們將實(shí)際的報(bào)紙名字m_name當(dāng)做參數(shù)傳給這個(gè)信號(hào)。當(dāng)接收者連接這個(gè)信號(hào)時(shí),就可以通過槽函數(shù)獲得實(shí)際值。這樣就完成了數(shù)據(jù)從發(fā)出者到接收者的一個(gè)轉(zhuǎn)移。
?
●?Reader類更簡單。因?yàn)檫@個(gè)類需要接受信號(hào),所以我們將其繼承了QObject,并且添加了Q_OBJECT宏。后面則是默認(rèn)構(gòu)造函數(shù)和一個(gè)普通的成員函數(shù)。Qt 5 中,任何成員函數(shù)、static 函數(shù)、全局函數(shù)和 Lambda 表達(dá)式都可以作為槽函數(shù)。與信號(hào)函數(shù)不同,槽函數(shù)必須自己完成實(shí)現(xiàn)代碼。槽函數(shù)就是普通的成員函數(shù),因此作為成員函數(shù),也會(huì)受到 public、private 等訪問控制符的影響。(如果信號(hào)是 private 的,這個(gè)信號(hào)就不能在類的外面連接,也就沒有任何意義。)
3.1自定義信號(hào)槽需要注意的事項(xiàng)
●發(fā)送者和接收者都需要是QObject的子類(當(dāng)然,槽函數(shù)是全局函數(shù)、Lambda 表達(dá)式等無需接收者的時(shí)候除外);
●使用?signals 標(biāo)記信號(hào)函數(shù),信號(hào)是一個(gè)函數(shù)聲明,返回 void,不需要實(shí)現(xiàn)函數(shù)代碼;
●槽函數(shù)是普通的成員函數(shù),作為成員函數(shù),會(huì)受到?public、private、protected 的影響;
●使用?emit 在恰當(dāng)?shù)奈恢冒l(fā)送信號(hào);
●使用QObject::connect()函數(shù)連接信號(hào)和槽。
●任何成員函數(shù)、static 函數(shù)、全局函數(shù)和 Lambda 表達(dá)式都可以作為槽函數(shù)
3.2信號(hào)槽的更多用法
●?一個(gè)信號(hào)可以和多個(gè)槽相連
如果是這種情況,這些槽會(huì)一個(gè)接一個(gè)的被調(diào)用,但是它們的調(diào)用順序是不確定的。
●多個(gè)信號(hào)可以連接到一個(gè)槽
只要任意一個(gè)信號(hào)發(fā)出,這個(gè)槽就會(huì)被調(diào)用。
●一個(gè)信號(hào)可以連接到另外的一個(gè)信號(hào)
當(dāng)?shù)谝粋€(gè)信號(hào)發(fā)出時(shí),第二個(gè)信號(hào)被發(fā)出。除此之外,這種信號(hào)-信號(hào)的形式和信號(hào)-槽的形式?jīng)]有什么區(qū)別。
●槽可以被取消鏈接
這種情況并不經(jīng)常出現(xiàn),因?yàn)楫?dāng)一個(gè)對(duì)象delete之后,Qt自動(dòng)取消所有連接到這個(gè)對(duì)象上面的槽。
●使用Lambda 表達(dá)式
在使用 Qt 5 的時(shí)候,能夠支持 Qt 5 的編譯器都是支持 Lambda 表達(dá)式的。
我們的代碼可以寫成下面這樣:
QObject::connect(&newspaper, static_cast<void (Newspaper:: *) (const QString &)>(&Newspaper::newPaper), [=](const QString &name) { /* Your code here. */ } );在連接信號(hào)和槽的時(shí)候,槽函數(shù)可以使用Lambda表達(dá)式的方式進(jìn)行處理。
回到頂部
4、Lambda表達(dá)式
C++11中的Lambda表達(dá)式用于定義并創(chuàng)建匿名的函數(shù)對(duì)象,以簡化編程工作。首先看一下Lambda表達(dá)式的基本構(gòu)成:
[函數(shù)對(duì)象參數(shù)](操作符重載函數(shù)參數(shù))mutable或exception?->返回值{函數(shù)體}
?①函數(shù)對(duì)象參數(shù);
[],標(biāo)識(shí)一個(gè)Lambda的開始,這部分必須存在,不能省略。函數(shù)對(duì)象參數(shù)是傳遞給編譯器自動(dòng)生成的函數(shù)對(duì)象類的構(gòu)造函數(shù)的。函數(shù)對(duì)象參數(shù)只能使用那些到定義Lambda為止時(shí)Lambda所在作用范圍內(nèi)可見的局部變量(包括Lambda所在類的this)。函數(shù)對(duì)象參數(shù)有以下形式:
?▲空。沒有使用任何函數(shù)對(duì)象參數(shù)。
▲=。函數(shù)體內(nèi)可以使用Lambda所在作用范圍內(nèi)所有可見的局部變量(包括Lambda所在類的this),并且是值傳遞方式(相當(dāng)于編譯器自動(dòng)為我們按值傳遞了所有局部變量)。
?▲&。函數(shù)體內(nèi)可以使用Lambda所在作用范圍內(nèi)所有可見的局部變量(包括Lambda所在類的this),并且是引用傳遞方式(相當(dāng)于編譯器自動(dòng)為我們按引用傳遞了所有局部變量)。
▲?this。函數(shù)體內(nèi)可以使用Lambda所在類中的成員變量。
▲?a。將a按值進(jìn)行傳遞。按值進(jìn)行傳遞時(shí),函數(shù)體內(nèi)不能修改傳遞進(jìn)來的a的拷貝,因?yàn)槟J(rèn)情況下函數(shù)是const的。要修改傳遞進(jìn)來的a的拷貝,可以添加mutable修飾符。
▲?&a。將a按引用進(jìn)行傳遞。
? ? ▲?a, &b。將a按值進(jìn)行傳遞,b按引用進(jìn)行傳遞。
▲?=,&a, &b。除a和b按引用進(jìn)行傳遞外,其他參數(shù)都按值進(jìn)行傳遞。
▲?&, a, b。除a和b按值進(jìn)行傳遞外,其他參數(shù)都按引用進(jìn)行傳遞。
int m = 0, n = 0; [=] (int a) mutable { m = ++n + a; }(4);[&] (int a) { m = ++n + a; }(4);[=,&m] (int a) mutable { m = ++n + a; }(4);[&,m] (int a) mutable { m = ++n + a; }(4);[m,n] (int a) mutable { m = ++n + a; }(4);[&m,&n] (int a) { m = ++n + a; }(4);② 操作符重載函數(shù)參數(shù);
標(biāo)識(shí)重載的()操作符的參數(shù),沒有參數(shù)時(shí),這部分可以省略。參數(shù)可以通過按值(如:(a,b))和按引用(如:(&a,&b))兩種方式進(jìn)行傳遞。
③ 可修改標(biāo)示符;
mutable聲明,這部分可以省略。按值傳遞函數(shù)對(duì)象參數(shù)時(shí),加上mutable修飾符后,可以修改按值傳遞進(jìn)來的拷貝(注意是能修改拷貝,而不是值本身)。
④ 錯(cuò)誤拋出標(biāo)示符;
exception聲明,這部分也可以省略。exception聲明用于指定函數(shù)拋出的異常,如拋出整數(shù)類型的異常,可以使用throw(int)
⑤ 函數(shù)返回值;
->返回值類型,標(biāo)識(shí)函數(shù)返回值的類型,當(dāng)返回值為void,或者函數(shù)體中只有一處return的地方(此時(shí)編譯器可以自動(dòng)推斷出返回值類型)時(shí),這部分可以省略。
⑥ 是函數(shù)體;
{},標(biāo)識(shí)函數(shù)的實(shí)現(xiàn),這部分不能省略,但函數(shù)體可以為空。
總結(jié):
?
?
案例代碼:
mainwidget.h
#ifndef MAINWIDGET_H #define MAINWIDGET_H#include <QWidget> #include <QPushButton> #include "subwidget.h" //子窗口頭文件class MainWidget : public QWidget {Q_OBJECTpublic:MainWidget(QWidget *parent = 0);~MainWidget();public slots:void mySlot();void changeWin();void dealSub();void dealSlot(int, QString);private:QPushButton b1;QPushButton *b2;QPushButton b3;SubWidget subWin; };#endif // MAINWIDGET_Hsubwidget.h
#ifndef SUBWIDGET_H #define SUBWIDGET_H#include <QWidget> #include <QPushButton>class SubWidget : public QWidget {Q_OBJECT public:explicit SubWidget(QWidget *parent = 0);void sendSlot();signals:/* 信號(hào)必須有signals關(guān)鍵字來聲明* 信號(hào)沒有返回值,但可以有參數(shù)* 信號(hào)就是函數(shù)的聲明,只需聲明,無需定義* 使用:emit mySignal();* 信號(hào)可以重載*/void mySignal();void mySignal(int, QString);public slots:private:QPushButton b; };#endif // SUBWIDGET_Hmain.cpp
#include "mainwidget.h" #include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);MainWidget w;//執(zhí)行MainWidget的構(gòu)造函數(shù)w.show();return a.exec(); }mainwidget.cpp
#include "mainwidget.h" #include <QPushButton> #include <QDebug> //打印MainWidget::MainWidget(QWidget *parent): QWidget(parent) {b1.setParent(this);b1.setText("close");b1.move(100, 100);b2 = new QPushButton(this);b2->setText("abc");connect(&b1, &QPushButton::pressed, this, &MainWidget::close);/* &b1: 信號(hào)發(fā)出者,指針類型* &QPushButton::pressed:處理的信號(hào), &發(fā)送者的類名::信號(hào)名字* this: 信號(hào)接收者* &MainWidget::close: 槽函數(shù),信號(hào)處理函數(shù) &接收的類名::槽函數(shù)名字* 發(fā)送-處理-接收-處理*//* 自定義槽,普通函數(shù)的用法* Qt5:任意的成員函數(shù),普通全局函數(shù),靜態(tài)函數(shù)* 槽函數(shù)需要和信號(hào)一致(參數(shù),返回值)* 由于信號(hào)都是沒有返回值,所以,槽函數(shù)一定沒有返回值*/connect(b2, &QPushButton::released, this, &MainWidget::mySlot);connect(b2, &QPushButton::released, &b1, &QPushButton::hide);/* 信號(hào):短信* 槽函數(shù):接收短信的手機(jī)*/setWindowTitle("老大");//this->setWindowTitle("老大");//等價(jià)同上b3.setParent(this);b3.setText("切換到子窗口");b3.move(50, 50);//顯示子窗口//subWin.show();connect(&b3, &QPushButton::released, this, &MainWidget::changeWin);//處理子窗口的信號(hào) // void (SubWidget::*funSignal)() = &SubWidget::mySignal; // connect(&subWin, funSignal, this, &MainWidget::dealSub);// void (SubWidget::*testSignal)(int, QString) = &SubWidget::mySignal; // connect(&subWin, testSignal, this, &MainWidget::dealSlot);//Qt4信號(hào)連接//Qt4槽函數(shù)必須有slots關(guān)鍵字來修飾connect(&subWin, SIGNAL(mySignal()), this, SLOT(dealSub()) );connect(&subWin, SIGNAL(mySignal(int,QString)),this, SLOT(dealSlot(int,QString)) );//缺點(diǎn): SIGNAL SLOT 將函數(shù)名字 -> 字符串 不進(jìn)行錯(cuò)誤檢查//Lambda表達(dá)式, 匿名函數(shù)對(duì)象//C++11增加的新特性, 項(xiàng)目文件: CONFIG += C++11//Qt配合信號(hào)一起使用,非常方便QPushButton *b4 = new QPushButton(this);b4->setText("Lambda表達(dá)式");b4->move(150, 150);int a = 10, b = 100;connect(b4, &QPushButton::clicked,// = :把外部所有局部變量、類中所有成員以值傳遞方式// this: 類中所有成員以值傳遞方式// & : 把外部所有局部變量, 引用符號(hào)[=](bool isCheck){qDebug() << isCheck;});resize(400, 300); }void MainWidget::dealSlot(int a, QString str) {// str.toUtf8() -> 字節(jié)數(shù)組QByteArray// ……data() -> QByteArray -> char *qDebug() << a << str.toUtf8().data(); }void MainWidget::mySlot() {b2->setText("123"); }void MainWidget::changeWin() {//子窗口顯示subWin.show();//本窗口隱藏this->hide(); }void MainWidget::dealSub() {//子窗口隱藏subWin.hide();//本窗口顯示show(); }MainWidget::~MainWidget() {}subwidget.cpp
#include "subwidget.h"SubWidget::SubWidget(QWidget *parent) : QWidget(parent) {this->setWindowTitle("小弟");b.setParent(this);b.setText("切換到主窗口");connect(&b, &QPushButton::clicked, this, &SubWidget::sendSlot);resize(400, 300); }void SubWidget::sendSlot() {emit mySignal();emit mySignal(250, "我是子窗口"); }SingnalAndSlot.pro
QT += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = 03_SignalAndSlot TEMPLATE = appSOURCES += main.cpp\mainwidget.cpp \subwidget.cppHEADERS += mainwidget.h \subwidget.hCONFIG += C++11總結(jié)
以上是生活随笔為你收集整理的C++框架_之Qt的信号和槽的详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何确定h.264的码率
- 下一篇: s3c2440移植MQTT