前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Qt中的信号槽

Qt中的信号槽

原创
作者头像
软件工程师Michael
发布2023-09-20 21:22:47
2810
发布2023-09-20 21:22:47
举报

一、信号槽的概念

类似于一些其它的编程语言或框架中的回调机制,信号槽是Qt基于C++语法新增的特性,使用起来非常方便,可以完成不同对象之间的通信。

信号槽的使用需要有以下两个条件:

  1. 通信的对象必须**继承自QObject类**,**QObject是Qt所有内置类型的基类**。
  2. 类中要有**Q_OBJECT宏**

二、函数原型

信号槽需要连接后才能触发,因此信号槽的**核心是连接函数,**连接函数是一个静态成员函数。

参数1:**发射者**,发射者是一个对象,此对象发射信号函数,**作为信号槽的触发条件。**

参数2:**信号函数**,参数1中的发射者发射出的信号函数,**作为信号槽的触发条件**。**需要使用 SIGNAL()包裹函数名称**

参数3:**接收者**,接收者是一个对象,此对象执行槽函数,**作为信号槽的执行结果**。

参数4:**槽函数**,参数3中接收者要执行的槽函数,**作为信号槽的执行结果。需要使用SLOT() 包裹函数名称。**

接收者绑定了发射者的信号函数,一旦发射者发射信号函数,接收者就执行槽函数。

三、连接方式

为了方便讲解,依次使用三种方式进行信号槽的连接。 - 自带信号 → 自带槽- 自带信号 → 自定义槽- 自定义信号 → 槽

3.1 自带信号 → 自带槽

这种方式是最简单的一种连接方式,因为信号函数和槽函数Qt都内置了,只需要程序员从文档中找到对应函数连接即可。

【例子】点击按钮,关闭窗口。

分析:先找因果关系的四个参数。

参数1:发射者,按钮对象

参数2:信号函数,点击

参数3:接收者,窗口对象

参数4:槽函数,关闭

mywidget.h

代码语言:javascript
复制
#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QPushButton>
#include <QWidget>

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    MyWidget(QWidget *parent = nullptr);
    ~MyWidget();
private:
    QPushButton *btn;
};
#endif // MYWIDGET_H

mywidget.cpp

代码语言:javascript
复制
#include "mywidget.h"

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    setFixedSize(400,400);
    // 实例一个按钮对象
    btn = new QPushButton("自带信号,自带槽演示", this);
    btn->move(100,100);
    // 连接槽和函数
    // 完成点击按钮关闭当前窗口
    // 标准写法
    connect(btn, SIGNAL(clicked()), this, SLOT(close()));
}

MyWidget::~MyWidget()
{
}

main.cpp

代码语言:javascript
复制
#include "mywidget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyWidget w;
    w.show();
    return a.exec();
}

3.2 自带信号 → 自定义槽

在实际的开发中,Qt不可能内置所有的函数,特别是槽函数,更多的情况是需要用户自定义一个槽函数来实现特定的功能,这种方式也是最常见的一种信号槽连接方式。

需要注意的是,槽函数是一种特殊的成员函数,实现槽函数的方式与普通成员函数类似。

注意:一定要先链接再触发信号 不然你虽然触发了信号但是接收者没有进行链接就触发不了槽函数

【例子】点击按钮,向右下方移动窗口并输出当前的窗口坐标。

参数1:按钮对象

参数2:clicked

参数3:窗口对象

参数4:自定义槽函数

dialog.h

代码语言:javascript
复制
#ifndef DIALOG_H
#define DIALOG_H
 
#include <QDialog>
#include <QPushButton>
#include <QDebug>
 
class Dialog : public QDialog
{
    Q_OBJECT
 
public:
    Dialog(QWidget *parent = 0);
    ~Dialog();
 
private:
    QPushButton *btn;
 
private slots: // 私有槽函数
    // 声明自定义槽函数
    void mySlot();
};
 
#endif // DIALOG_H

dialog.cpp

代码语言:javascript
复制
#include "dialog.h"
 
Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(400,400);
    btn = new QPushButton("向右下方移动",this);
    btn->setGeometry(100,100,100,100);
 
    // 连接信号槽
    //    参数1:按钮对象 btn
    //    参数2:clicked
    //    参数3:窗口对象 this
    //    参数4:自定义槽函数 mySlot
    connect(btn,SIGNAL(clicked()),this,SLOT(mySlot()));//类内通过this指针找到w,
          第三个参数为什么是this因为自定义信号槽函数属于Dialog类而这个类只有一个对象就是w,
          类内想要调w就必须用this
}
//法一:手写 法二:再定义中鼠标中点击重构
void Dialog::mySlot()//类内声明类外定义必须加作用域限定符 
{
    // 先获得当前窗口的坐标
    int x = this->x();
    int y = this->y();
    // 增加后移动
    move(x+10,y+10);
    // 输出当前坐标
    qDebug() << x+10 << "," << y+10;
}
 
Dialog::~Dialog()
{
    
}

3.3 自定义信号 → 槽

这种做法主要用于后期一些稍微复杂的场景,现在讲解无法使用合适案例演示,因此讲解的过程中并不是最优解,属于强行使用。

【例子】点击按钮,关闭窗口。

之前的思路:

现在的思路:

现在的思路需要有两个信号槽的连接,在自定义槽函数中要手动发射一个自定义信号函数,信号函数是一种非常特殊的函数,信号函数只有声明,没有定义;信号函数没有权限。

首先按钮与窗口进行链接connect 再点击按钮 按钮发射一个信号 由于两者绑定所以窗口会收到这个信号并触发槽函数,然后再去链接connect窗口与窗口本身就是自己链接自己 上一个触发的槽函数里面是一个自定义信号 然后发射这个自定义信号 窗口接受 并执行相应的槽函数?

dialog.h

代码语言:javascript
复制
#ifndef DIALOG_H
#define DIALOG_H

#include <QLineEdit>
#include <QPushButton>
#include <QWidget>

class Dialog : public QWidget
{
    Q_OBJECT
public:
    explicit Dialog(QWidget *parent = nullptr);
private slots:
    void mySlot(); // 自定义槽
    void mySlot1();

signals:
    void mySignal(); // 自定义信号
private:
    QPushButton *btn;
    QLineEdit *txt;

};

#endif // DIALOG_H

dialog.cpp

代码语言:javascript
复制
#include "dialog.h"

Dialog::Dialog(QWidget *parent) : QWidget(parent)
{
    // 设置窗口大小
    setFixedSize(600,400);
    // 实例化一个QLineEdit对象
    txt = new QLineEdit(this);
    txt->setGeometry(260,100,170,50);
    // 实例化一个按钮对象
    btn = new QPushButton("自定义槽和信号操作",this);
    // 设置位置和大小
    btn->setGeometry(100,100,150,50);
    // 连接信号和槽函数
    connect(btn, SIGNAL(clicked()), this, SLOT(mySlot()));
    // 给窗体连接自定义信号和自带槽函数
    connect(this, SIGNAL(mySignal()), this, SLOT(mySlot1()));
}

void Dialog::mySlot()
{
    // 手动触发自定义信号
    emit mySignal();
}

void Dialog::mySlot1()
{
    txt->setText("触发了自定义信号和槽函数");
}

【小结】

信号槽是个较新的概念,需要花点时间细细品味,细嚼慢咽,然后在理解的基础上运用。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、信号槽的概念
  • 二、函数原型
  • 三、连接方式
    • 3.1 自带信号 → 自带槽
      • 3.2 自带信号 → 自定义槽
        • 3.3 自定义信号 → 槽
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
        http://www.vxiaotou.com