Qt5学习应用之路--信号与槽(signal & slot)

概述:

 信号与槽是 Qt 框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。

信号和槽是Qt特有的信息传输机制,是Qt设计程序的重要基础,它可以让互不干扰的对象建立一种联系。

 槽的本质是类的成员函数,其参数可以是任意类型的。和普通C++成员函数几乎没有区别,它可以是虚函数;也可以被重载;可以是公有的、保护的、私有的、也可以被其他C++成员函数调用。唯一区别的是:槽可以与信号连接在一起,每当和槽连接的信号被发射的时候,就会调用这个槽。

 槽能被用来接收信号,除此之外它们也是普通的成员函数。槽不知道是否有信号与它连接起来,正如对象不知道它发出信号是否会被接收一样。这样的机制确保了可以使用Qt创建一个个完全独立的组件。你可以把你感兴趣的多个信号与一个个槽进行连接,也可以把一个信号与多个槽进行连接。甚至可以直接把一个信号连接到另一个信号(当第一个信号发送出去的时候,第二个信号紧接着被发送)。就这样,信号与插槽建立了强大的组件编程机制。

connect()函数最常用的一般形式:
connect(sender, signal, receiver, slot);

参数:

  • sender:发出信号的对象

  • signal:发出信号的对象发出的信号

  • receiver:接收信号的对象

  • slot:接收信号的对象在接收到信号之后所需要调用的函数

 信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。如果不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少),但是不能说信号根本没有这个数据,你就要在槽函数中使用(就是槽函数的参数比信号的多,这是不允许的)。

信号与槽的书写方式

Qt5的方式:
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();
}
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(); 
}

Qt4使用了SIGNAL和SLOT这两个宏,将两个函数名转换成了字符串。Qt5的方式在语法上是完全兼容Qt4的。

总结

在这里插入图片描述

信号与槽之emit的使用

 程序中定义了三个信号、三个槽函数,然后将信号与槽进行了关联,每个槽函数只是简单的弹出一个对话框窗口。

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMessageBox>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

// 信号声明区
signals:
    // 声明信号 mySignal()
    void mySignal();
    // 声明信号 mySignal(int)
    void mySignal(int x);
    // 声明信号 mySignalParam(int,int)
    void mySignalParam(int x,int y);
// 槽声明区
public slots:
    // 声明槽函数 mySlot()
    void mySlot();
    // 声明槽函数 mySlot(int)
    void mySlot(int x);
    // 声明槽函数 mySignalParam (int,int)
    void mySlotParam(int x,int y);


private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 将信号 mySignal() 与槽 mySlot() 相关联
    connect(this,SIGNAL(mySignal()),SLOT(mySlot()));
    // 将信号 mySignal(int) 与槽 mySlot(int) 相关联
    connect(this,SIGNAL(mySignal(int)),SLOT(mySlot(int)));
    // 将信号 mySignalParam(int,int) 与槽 mySlotParam(int,int) 相关联
    connect(this,SIGNAL(mySignalParam(int,int)),SLOT(mySlotParam(int,int)));
}

MainWindow::~MainWindow()
{
    delete ui;
}


// 定义槽函数 mySlot()
void MainWindow::mySlot()
{
    QMessageBox::about(this,"Tsignal", "This is a signal/slot sample without parameter.");
}
// 定义槽函数 mySlot(int)
void MainWindow::mySlot(int x)
{
    QMessageBox::about(this,"Tsignal", "This is a signal/slot sample with one parameter.");
}
// 定义槽函数 mySlotParam(int,int)
void MainWindow::mySlotParam(int x,int y)
{
    char s[256];
    sprintf(s,"x:%d y:%d",x,y);
    QMessageBox::about(this,"Tsignal", s);
}


void MainWindow::on_pushButton_clicked()
{
    // 发射信号 mySignal()
    emit mySignal();
    // 发射信号 mySignal(int)
    emit mySignal(5);
    // 发射信号 mySignalParam(5,100)
    emit mySignalParam(5,100);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值