卓越 網(wǎng)站建設(shè) 深圳西鄉(xiāng)競價(jià)托管
QT信號(hào)和槽與自定義的信號(hào)和槽
1.概述
這篇文章介紹下QT信號(hào)和槽的入門知識(shí),通過一個(gè)案例介紹如何創(chuàng)建信號(hào)和槽,并調(diào)用他們。
2.信號(hào)和槽使用
下面通過點(diǎn)擊按鈕關(guān)閉窗口的案例介紹如何使用信號(hào)和槽。
- 創(chuàng)建按鈕
在widget.cpp文件中創(chuàng)建按鈕代碼如下
#include "mywidget.h"
#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent)
{// 第二種創(chuàng)建按鈕方式QPushButton *btn2 = new QPushButton("構(gòu)造按鈕",this);
- 使用信號(hào)和槽實(shí)現(xiàn)點(diǎn)擊按鈕關(guān)閉窗口
使用QObject類中的connect函數(shù)連接信號(hào)和槽,該函數(shù)需要4個(gè)參數(shù)- 參數(shù)1: 發(fā)送者,誰發(fā)送信號(hào)——btn2
- 參數(shù)2: 發(fā)送的是什么信號(hào),信號(hào)用函數(shù)地址——&QPushButton::clicked
- 參數(shù)3: 接受者,誰來接受信號(hào)——this指的是當(dāng)前窗口對象
- 參數(shù)4: 槽,接受者做出的動(dòng)作——&QWidget::close
connect(btn2, &QPushButton::clicked, this, &QWidget::close);
3.如何查看QT提供的信號(hào)和槽函數(shù)
在使用connect連接信號(hào)和槽的時(shí)候,第一個(gè)參數(shù)發(fā)送者是btn2按鈕對象,屬于QPushButton類。
如何查看系統(tǒng)提供的信號(hào)?
第二個(gè)參數(shù)需要知道發(fā)送什么信號(hào),這個(gè)時(shí)候怎么知道QPushButton提供了哪些信號(hào)那,這就需要查看QT幫助文檔。
首先在編輯器中點(diǎn)擊HELP
打開幫助文檔,輸入QPush查看QPushButton
中提供的內(nèi)容沒有Signal
信號(hào)。
接著查看QPushButton
父類
在父類中看到有Signals
信號(hào),點(diǎn)擊它,跳轉(zhuǎn)到信號(hào)介紹位置。
在信號(hào)介紹中給出了所有的信號(hào),我們選擇第一個(gè)就是我們示例中的點(diǎn)擊信號(hào)。在使用這個(gè)信號(hào)函數(shù)時(shí)候一定要用地址引用方式調(diào)用它,就是在調(diào)用前加上&
符號(hào)。
connect(btn2, &QPushButton::clicked, this, &QWidget::close);
如何查看系統(tǒng)提供的槽?
查看方法和上面查看信號(hào)一樣,我們是關(guān)閉窗口,窗口的類是QWidge
,查看它的槽中提供了close()
函數(shù)。
connect(btn2, &QPushButton::clicked, this, &QWidget::close);
3.自定義信號(hào)和槽功能
上面介紹的是使用QT提供的信號(hào)和槽,下面通過一個(gè)實(shí)例介紹如何自定義自己的信號(hào)和槽的功能。
示例功能描述
老師類發(fā)出一個(gè)下課的信號(hào),學(xué)生類的槽執(zhí)行請客吃飯
- 新建項(xiàng)目
首先新建一個(gè)QWidge
類型項(xiàng)目,然后在項(xiàng)目名稱上右鍵,新建clss文件,名稱輸入
Teacher
。然后再新建另一個(gè)class文件,名稱輸入Student
。
2. 創(chuàng)建信號(hào)
在teacher.h
文件中創(chuàng)建信號(hào), 信號(hào)只需要定義不需要實(shí)現(xiàn)。
#ifndef TEACHER_H
#define TEACHER_H#include <QObject>class Teacher : public QObject
{Q_OBJECT
public:explicit Teacher(QObject *parent = nullptr);signals:/* 自定義信號(hào),寫到signals中* 返回值是void,只需要聲明不需要實(shí)現(xiàn)* 可以有參數(shù),可以重載*/void hungry();};#endif // TEACHER_H
- 創(chuàng)造槽
在student.h
文件中創(chuàng)建槽函數(shù),槽函數(shù)聲明后需要在student.cpp
文件中實(shí)現(xiàn)功能。
#ifndef STUDENT_H
#define STUDENT_H#include <QObject>class Student : public QObject
{Q_OBJECT
public:explicit Student(QObject *parent = nullptr);signals:public slots:/* 早起QT版本,必須寫到public slots, 高級(jí)版本可以寫到public或者全局中* 返回值void, 需要聲明并且實(shí)現(xiàn)* 可以有參數(shù),可以重載
*/void treat();};#endif // STUDENT_H
在student.cpp
文件中實(shí)現(xiàn)功能
#include "student.h"
#include <QDebug>Student::Student(QObject *parent) : QObject(parent)
{}void Student::treat()
{qDebug() << "執(zhí)行槽函數(shù),請客吃飯";
}
- 連接信號(hào)和槽
在QWidget.h
文件中創(chuàng)建Teacher和Student類對象,創(chuàng)建一個(gè)觸發(fā)下課的函數(shù)。
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include "teacher.h"
#include "student.h"QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();
// 創(chuàng)建Teacher和Student類對象Teacher *tc;Student *st;private:Ui::Widget *ui;
// 創(chuàng)建一個(gè)觸發(fā)下課的函數(shù)void classIsDown();
};
#endif // WIDGET_H
在QWidget.cpp
文件中實(shí)現(xiàn)信號(hào)和槽的功能
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 1.創(chuàng)建對象this->tc = new Teacher(this);this->st = new Student(this);
// 2.連接信號(hào)和槽connect(tc, &Teacher::hungry, st, &Student::treat);
// 3.調(diào)用觸發(fā)下課函數(shù)classIsDown();
}//4.下課函數(shù)使用emit發(fā)送信號(hào)
void Widget::classIsDown()
{emit tc->hungry();
}
Widget::~Widget()
{delete ui;
}
4.信號(hào)和槽函數(shù)重載
當(dāng)我們自定義信號(hào)和槽函數(shù)時(shí),他們可以通過參數(shù)進(jìn)行重載,實(shí)現(xiàn)更多的功能。當(dāng)使用重載時(shí),調(diào)用的時(shí)候需要使用函數(shù)指針指向函數(shù)地址,確認(rèn)調(diào)用哪個(gè)重載的函數(shù)。
繼續(xù)使用上面的示例,在Teacher和Student類中添加重載的信號(hào)和槽
- 添加重載的信號(hào)
在teacher.h文件中新增void hungry(QString foodName);
有參的信號(hào)
#ifndef TEACHER_H
#define TEACHER_H#include <QObject>class Teacher : public QObject
{Q_OBJECT
public:explicit Teacher(QObject *parent = nullptr);signals:/* 自定義信號(hào),寫到signals中* 返回值是void,只需要聲明不需要實(shí)現(xiàn)* 可以有參數(shù),可以重載*/void hungry();
// 信號(hào)參數(shù)重載void hungry(QString foodName);};#endif // TEACHER_H
- 添加重載的槽
在student.h文件中添加void treat(QString foodName);
槽函數(shù)
#ifndef STUDENT_H
#define STUDENT_H#include <QObject>class Student : public QObject
{Q_OBJECT
public:explicit Student(QObject *parent = nullptr);signals:public slots:/* 早起QT版本,必須寫到public slots, 高級(jí)版本可以寫到public或者全局中* 返回值void, 需要聲明并且實(shí)現(xiàn)* 可以有參數(shù),可以重載
*/void treat();// 槽參數(shù)重載void treat(QString foodName);};#endif // STUDENT_H
在student.cpp文件中實(shí)現(xiàn)槽函數(shù)功能
#include "student.h"
#include <QDebug>Student::Student(QObject *parent) : QObject(parent)
{}void Student::treat()
{qDebug() << "執(zhí)行槽函數(shù),請客吃飯";
}void Student::treat(QString foodName)
{qDebug() << "執(zhí)行參數(shù)重載的槽函數(shù),吃" << foodName.toUtf8().data();
}
- 調(diào)用重載的信號(hào)和槽函數(shù)
在widget.cpp文件中通過connect()函數(shù)調(diào)用信號(hào)和槽之前需要先指明調(diào)用的是有參的信號(hào)和槽函數(shù),方法如下
// 調(diào)用有參的信號(hào)和槽
// 1.聲明一個(gè)函數(shù)指針,指向函數(shù)地址void(Teacher::*teacherSignal) (QString) = &Teacher::hungry;void(Student::*studentSlot)(QString) = &Student::treat;
// 2.連接信號(hào)和槽connect(tc, teacherSignal, st, studentSlot);
完整代碼
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 1.創(chuàng)建對象this->tc = new Teacher(this);this->st = new Student(this);
// 2.連接信號(hào)和槽
// connect(tc, &Teacher::hungry, st, &Student::treat);
// 3.調(diào)用觸發(fā)下課函數(shù)
// classIsDown();// 調(diào)用有參的信號(hào)和槽
// 1.聲明一個(gè)函數(shù)指針,指向函數(shù)地址void(Teacher::*teacherSignal) (QString) = &Teacher::hungry;void(Student::*studentSlot)(QString) = &Student::treat;
// 2.連接信號(hào)和槽connect(tc, teacherSignal, st, studentSlot);
// 3.調(diào)用觸發(fā)下課函數(shù)classIsDown();
}//4.下課函數(shù)使用emit發(fā)送信號(hào)
void Widget::classIsDown()
{
// 調(diào)用無參信號(hào)
// emit tc->hungry();
// 調(diào)用有參信號(hào)emit tc->hungry("糖醋里脊");
}
Widget::~Widget()
{delete ui;
}
5.信號(hào)連接信號(hào)
上面觸發(fā)信號(hào)使用的是emit,如果我們想實(shí)現(xiàn)通過點(diǎn)擊按鈕來觸發(fā)信號(hào),那么可以采用普通的按鈕發(fā)送信號(hào)控制槽函數(shù),還可以采用信號(hào)連接信號(hào)實(shí)現(xiàn)。
// 點(diǎn)擊按鈕觸發(fā)下課,第一種方式通過信號(hào)和槽實(shí)現(xiàn)。QPushButton *btn = new QPushButton("下課",this);this->resize(600,400);
// connect(btn, &QPushButton::clicked, this, &Widget::classIsDown);// 點(diǎn)擊按鈕觸發(fā)下課,第二種通過信號(hào)連接信號(hào)實(shí)現(xiàn)void(Teacher::*teacherSignal2) (void) = &Teacher::hungry;void(Student::*studentSlot2)(void) = &Student::treat;connect(tc, teacherSignal2, st, studentSlot2);// 通過一個(gè)按鈕信號(hào),鏈接到上面Teacher的信號(hào),觸發(fā)上面的信號(hào)和槽執(zhí)行
// 當(dāng)點(diǎn)擊按鈕時(shí),按鈕發(fā)送信號(hào)給teacher的信號(hào),teacher信號(hào)被觸發(fā)就會(huì)發(fā)送信號(hào)給student槽函數(shù)connect(btn, &QPushButton::clicked, tc, teacherSignal2);
6.斷開信號(hào)
使用disconnect函數(shù)斷開信號(hào),函數(shù)中的參數(shù)就是要斷開鏈接connect里面的參數(shù)。
// 點(diǎn)擊按鈕觸發(fā)下課,第二種通過信號(hào)連接信號(hào)實(shí)現(xiàn)void(Teacher::*teacherSignal2) (void) = &Teacher::hungry;void(Student::*studentSlot2)(void) = &Student::treat;connect(tc, teacherSignal2, st, studentSlot2);// 通過一個(gè)按鈕信號(hào),鏈接到上面Teacher的信號(hào),觸發(fā)上面的信號(hào)和槽執(zhí)行connect(btn, &QPushButton::clicked, tc, teacherSignal2);// 斷開信號(hào)disconnect(tc, teacherSignal2, st, studentSlot2);
7.擴(kuò)展
- QT4版本信號(hào)和槽寫法
// QT4版本信號(hào)和槽connect(tc,SIGNAL(hungry()), st, SLOT(treat()));