信號:
* 信號必學用signals關鍵字來聲明,signals是Qt拓展的關鍵字
* 信號沒有返回值,但可以有參數
* 信號就是函數聲明,只需聲明,無需定義
* 使用: emit mySignal();
* 信號可以重載
使用connec進行從指定類型將信號發送給接受對象的方法的鏈接,例如:
connect(&b1,&QPushButton::pressed,this,&MyWidget::close); /*參數: * &b1:信號發出者,指針類型 * &QPushButton:pressed:處理的信號,&發送者的類名::信號名字 * this:信號接受者 * &MyWidget::close:槽函數,即信號處理函數,&接受的類名::槽函數 */
自定義槽函數:
* Qt5:任意成員函數,普通全局函數,靜態函數
* 槽函數需要和信號一致(參數,返回值)
* 由於信號沒有返回值,所以,槽函數一定沒有返回值,例如:
connect(&b2,&QPushButton::released,this,&MyWidget::mySlot); //槽函數 void MyWidget::mySlot() { //b2是一個QPushButton類型 b2.setText("123"); }
無參數信號:
例如:
//定義一個信號 signals: void mySignal(); //使用信號 void SubWidget::sendSlot() { emit mySignal(); }
信號和槽函數使用示例:
功能:切換窗口,並隱藏當前窗口
主窗口
class MyWidget : public QWidget { Q_OBJECT public: MyWidget(QWidget *parent = 0); void mySlot(); void changeWin(); void dealSub(void); ~MyWidget(); private: QPushButton b1; //窗口關閉按鈕 QPushButton b3; //切換窗口按鈕 SubWidget w; //另一獨立窗口 };
方法實現:
MyWidget::MyWidget(QWidget *parent) : QWidget(parent),b1(this) { b1.setText("close"); b1.move(100,100); connect(&b1,&QPushButton::pressed,this,&MyWidget::close); setWindowTitle("老大");//設置窗口標題 b3.setParent(this); //綁定父對象 b3.setText("切換到子窗口"); b3.move(50,50); connect(&b3,&QPushButton::released,this,&MyWidget::changeWin); connect(&w,&SubWidget::mySignal,this,&MyWidget::dealSub); } void MyWidget::dealSub() { w.hide(); this->show(); } void MyWidget::changeWin() { w.show(); this->hide(); } MyWidget::~MyWidget(){}
第二個窗口:
class SubWidget : public QWidget { Q_OBJECT public: explicit SubWidget(QWidget *parent = nullptr); void sendSlot();//槽函數 signals: void mySignal(); public slots: private: QPushButton b1;//切換窗口按鈕 };
方法實現:
SubWidget::SubWidget(QWidget *parent) : QWidget(parent) { this->setWindowTitle("小弟"); b1.setParent(this); b1.setText("切換到主窗口"); //當按鍵按下時產生信號,調用sendSlot發送信號mySignal() connect(&b1,&QPushButton::clicked,this,&SubWidget::sendSlot); } void SubWidget::sendSlot() { emit mySignal(); }
有參數的信號:
信號重載后,會照成二義性問題,信號和槽函數必須一制,即參數列表類型和順序一樣,但參數個數可以不一樣(Ps:信號的參數個數大於等於槽函數參數個數,反之不可)。
信號:
void mySignal(int,QString);
emit mySignal(250,"我是子窗口");
槽函數:
void MyWidget::dealSlot(int a,QString str) { //str.toUtf8()轉換成字節數組QByteArray //.............data() 轉換成char* qDebug() << a << str.toUtf8().data(); }
解決方法如下:
1.通過不同的函數指針,區分接收到的信號
void (SubWidget::*funSignal)() = &SubWidget::mySignal; void (SubWidget::*testSignal)(int,QString) = &SubWidget::mySignal; connect(&w,funSignal,this,&MyWidget::dealSub); connect(&w,testSignal,this,&MyWidget::dealSlot);
2.使用Qt4中的方法:
* Qt4槽函數必須有slots關鍵字修飾
* 缺陷:SIGNAL SLOT 將函數名字轉換成字符串,不進行錯誤檢查
* 建議:使用Qt5的處理方法
類中定義:
...... public slots: void mySlot(); void changeWin(); void dealSub(); void dealSlot(int,QString); ......
函數實現中應用:
...... connect(&w,SIGNAL(mySignal(int,QString)),this,SLOT(dealSlot(int,QString))); connect(&w,SIGNAL(mySignal()),this,SLOT(dealSub())); ......
Lambda表達式:匿名函數對象
* C++11新增加的特性,配合信號使用,非常方便
* 需要在項目文件添加:CONFIG += C++11
QPushButton *b4 = new QPushButton(this); b4->setText("Lambda表達式"); b4->move(150,150); int a=10,b=100; /* * []用來傳遞外部參數, * = :把外部所有局部變量,類中所有成員以值傳遞方式,但是是只讀的,使用mutable改變, * this:類中所有成員以值傳遞方式 * & :把外部所有局部變量以值傳遞方式,避免使用 * () :接受到的參數 */ connect(b4,&QPushButton::clicked, [=](bool isCheck)mutable { qDebug() << "111111"; qDebug() << a << b; qDebug() << isCheck; a = 11; } );
*是在上面示例程序中的信號(我自己理解的,如有錯誤,還請指出)
released():當按鍵釋放時產生
pressed() :當按鍵按下時產生
clicked(bool checked = false) :當按鍵被激活時產生(按鈕被按下,然后釋放)