Qt5------信號和槽函數


信號:

  * 信號必學用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) :當按鍵被激活時產生(按鈕被按下,然后釋放)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM