一、什么是信号与槽
信号(Signal)就是在特定情况下被发射的事件,例如 PushButton 最常见的信号就是鼠标
单击时发射的 clicked() 信号。
槽(Slot)就是对信号响应的函数。槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。
举个例子:
对应于下图:老师是发送者,让一个学生回答问题(发出信号),学生就是接收者,需要回答问题(槽)。
二、通过ui界面连接信号与槽
①将发送对象Push Button拖到MainWindow中
②连接信号与槽
点击+号,添加信号与槽的连接,并选择发送者为pushButton,发送信号clicked(),接受者MainWindow,槽close()。
③ 运行结果
当点击,PushButton的时候,MainWindow会关闭。
通过ui界面连接信号与槽得本质,也是编写相应的代码 ,进入ui_mainwindow头文件
#include "ui_mainwindow.h"
可以查看到一下注释:说明该头文件下的代码是每次编译都会更新的,因此在这里面修改是没有效果的。
/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
** Created by: Qt User Interface Compiler version 5.12.9
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
可以在ui_mainwindow中查看到一下代码:
QObject::connect(pushButton, SIGNAL(clicked()), MainWindow, SLOT(close()));
其作用就是将 pushButton 按钮的 clicked() 信号与窗体(MainWindow)的槽函数 close() 相
关联,这样,当单击 pushButton 按钮(就是界面上的“X”按钮)时,就会执行 MainWindow
的 close() 槽函数。
三、编写函数连接信号与槽
信号与槽关联是用 QObject::connect() 函数实现的,其基本格式是:
QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));
由于QObject是所有Qt类的基类,所以调用connect函数的时候不需要加QObkect::
① 使用connect函数连接pushButton和MainWindow
修改mainWindow.cpp如下:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(close()));
}
MainWindow::~MainWindow()
{
delete ui;
}
上述代码在MainWindow的构造函数中,实现了发送者pushButton,信号clicked(),this指针指向MainWindow,槽close()的连接。
四、自定义信号与槽
下面将按照如下模型,自定义信号与槽。
① 首先创建Teacher类,选择基类为QObject,同理创建学生Student类
② 在Teacher和Student头文件中声明信号与槽
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
//声明一个信号,无需定义
void SendMessege();
};
#endif // TEACHER_H
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
signals:
public slots:
//声明一个槽,必须定义
void AnsweQuestion();
};
#endif // STUDENT_H
记住!!槽在声明以后必须添加定义,否则会报错,而信号则不需要定义也不会报错!!
③ 对槽添加定义:
右键选中声明的槽电机Refactor->在Student.cpp中添加定义
添加定义后Student.cpp文件内容如下:
#include "student.h"
#include <QDebug>
Student::Student(QObject *parent) : QObject(parent)
{
}
void Student::AnsweQuestion()
{
qDebug() << "学生回答问题" << endl;
}
④ 在MainWindow类中,定义私有对象
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "student.h"
#include "teacher.h"
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class Teacher;
class Student; //声明学生和老师类
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
Teacher *teacher;
Student *student;
};
#endif // MAINWINDOW_H
⑤ 在MainWindow的构造函数中,为teacher和student分配内存,并连接信号与槽,最后利用emit发送信号
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
teacher = new Teacher(this);
student = new Student(this);
connect(teacher, SIGNAL(SendMessege()), student, SLOT(AnsweQuestion()));
emit teacher->SendMessege();
}
MainWindow::~MainWindow()
{
delete ui;
}
⑥ 运行实例
当运行代码时,会在窗口打印文字