当前位置: 首页 > article >正文

Qt 5.14.2 学习记录 —— 사 信号与槽机制(1)

文章目录

  • 1、概念
  • 2、connect
  • 3、自定义槽函数
  • 4、自定义信号


1、概念

Qt中,控件和用户的操作都会发出信号,比如点击按钮,移动鼠标等,信号的处理函数就是槽。Qt可以用connect来把信号和槽关联起来,这样只要信号触发,就自动执行对应的槽函数。槽函数本身也是一个回调函数。对于回调来说,对应的处理方法都是提前准备好的。Qt中必须要先关联好信号和槽,再触发信号。

2、connect

connect是QObject的静态成员函数。Qt的类都是存在继承关系的,比如PushButton,LineEdit的父类都是QWidget,QWidget就是控件,QWidget的父类是QObject,所有Qt的类都直接或间接继承自QObject类,所以Qt中的类都可以直接使用connect。

在这里插入图片描述

最后一个参数是默认参数,暂且不考虑。

sender表示信号源,也就是哪个控件发出的信号。

signal表示信号类型。

receiver表示哪个对象接收信号,method就是信号处理函数。

写一个按钮,一点击就关闭窗口。widget.cpp:

#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    
    QPushButton* button = new QPushButton(this);
    button->setText("Exit");
    button->move(330, 250);
    
    connect(button, &QPushButton::clicked, this, &Widget::close);
}

connect前两个参数和后两个参数必须是分别匹配的,button是什么类型,那么第二个参数的信号就必须是这个类型内置的信号或者它的父类的信号。

写第二个参数时,写clicked时会出现两个写法,一个是click,一个是clicked,两个前面都有一个符号,click的符号代表槽函数,clicked的符号代表信号类型。

槽函数直接用内置函数。

Qt中很多按钮存在共性内容,这些共性内容放置在QAbstractButton类中,这些按钮类都继承自这个类,clicked信号就在这个父类中。当按钮被激活时,clicked信号就会被发出。

二四两个参数是const char的参数,传的时候需要给信号搭配一个SIGNAL宏,给槽函数搭配一个SLOT宏,都转为char后才能传:

connect(button, SIGNAL(&QPushButton::clicked), this, SLOT(&Widget::close));

但Qt5之后给connect做了重载函数,这两个参数就变成了泛型参数,允许传入任意类型的指针了。不过如果参数不匹配也不行。

3、自定义槽函数

在Widget类里写一个自定义的成员函数的声明,widget.cpp中写上实现,我们就可以直接用这个函数了。

widget.h:

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    
    void handleClicked();

private:
    Ui::Widget *ui;
};

widget.cpp:

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

    QPushButton* button = new QPushButton(this);
    button->setText("Button");
    button->move(330, 250);

    connect(button, &QPushButton::clicked, this, &Widget::close);
}

void Widget::handleClicked()
{
    // 点击按钮就修改窗口标题
    this->setWindowTitle("Button clicked");
}

更简单的方式是直接操作图形化界面。

将PushButton拖拽过来后,右击选择转到槽

在这里插入图片描述

可以看到来到了它的直接的父类QAbstractButton,以及QA的父类QWidget,以及QW的父类QObject。点击click(),就来到widget.cpp文件,并且自动写出了一个函数框架,代码部分则由用户自定义。

在这里插入图片描述

此时连接信号和槽就不是connect,而是通过函数名字,也就是选择click()后自动转到的,Qt自动生成的函数名来连接信号和槽。函数名字得符合命名规则,如果把clicked改为click,PushButton并没有对应的函数,那么就不生效,报警告,因为无法连接上。

在这里插入图片描述
调用connectSlotsByName就会触发连接,在生产时的实时文件ui_widget.h中会看到该函数。

4、自定义信号

信号本质是一个函数,但和槽函数不同,槽函数在Qt 5以及更高版本中,槽函数和普通成员函数之间已经没什么区别了;但信号特殊,用户只需要写出函数声明,并能让Qt知道这是一个信号,那么函数的定义,Qt会在编译过程中自动生成,而且对于自动生成过程,用户无法进行操作。

作为信号函数,返回值必须为void,参数有无都可,且也可以支持重载。

在写信号时,现在头文件中Widget类的public部分写上signal关键字,这是Qt的关键字,qmake生成代码时扫描到类中包含signals关键字时就会自动把下面的函数声明当作信号,并生成函数定义。

// widget.h

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void handleMySignal();

signals:
    void mySignal();

private:
    Ui::Widget *ui;
};

// widget.cpp

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

    connect(this, &Widget::mySignal, this, &Widget::handleMySignal);

    // 连接好后用emit来发送信号
    emit mySignal();
}

void Widget::handleMySignal()
{
    this->setWindowTitle("处理自定义信号");
}

运行后发现窗口标题变为处理自定义信号了。

我们也可以把发送并处理信号放到一个按钮中,按钮的自定义槽函数按照控件方式来写:

// widget.h

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void handleMySignal();

signals:
    void mySignal();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
};

// widget.cpp

#include <QPushButton>

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

void Widget::handleMySignal()
{
    this->setWindowTitle("处理自定义信号");
}

void Widget::on_pushButton_clicked()
{
    connect(this, &Widget::mySignal, this, &Widget::handleMySignal);

    // 连接好后用emit来发送信号
    emit mySignal();
}

在Qt 5以上,不写emit也可以,因为处理signals部分时都会自动发送信号。不过也应该写,可读性更强。

结束。


http://www.kler.cn/a/465878.html

相关文章:

  • 设计模式 结构型 适配器模式(Adapter Pattern)与 常见技术框架应用 解析
  • [python3]Excel解析库-xlutils
  • PWN 的知识之如何利用栈溢出利用后门函数
  • matlab中高精度计算函数vpa与非厄米矩阵本征值的求解
  • 《学校一卡通管理系统》数据库MySQL的设计与实现
  • 《代码随想录》Day25打卡!
  • 黑马JavaWeb开发跟学(十四).SpringBootWeb原理
  • 基于Swarm的大模型应用:一个天气助手
  • uniapp Stripe 支付
  • 解决ubuntu服务器SSH连接卡顿,连上后命令输入也是卡顿以及如何在Ubuntu上杀死不断重启的进程。
  • 【连续3届JPCS出版,EI稳定检索!】第四届能源利用与自动化国际学术会议(ICEUA 2025)
  • [cg] android studio 无法调试cpp问题
  • SQL中的REGEXP正则表达式使用指南
  • 抢先体验:人大金仓数据库管理系统KingbaseES V9 最新版本 CentOS 7.9 部署体验
  • Debian安装配置MariaDB
  • 安卓系统主板_迷你安卓主板定制开发_联发科MTK安卓主板方案
  • 期权懂|期权入门知识:平值期权的杠杆有多少倍数?
  • 基于微信小程序的自修室预约系统
  • Nginx 配置 SSL(HTTPS)详解
  • JVM常见排查问题的命令及可视化工具
  • 以一个实际例子来学习Linux驱动程序开发之“设备类”的相关知识【利用设备类实现对同一设备类下的多个LED灯实现点亮或关闭】
  • 服务器迁移中心——“工作组迁移”使用指南
  • 开源Material Design WPF UI 控件库简单上手
  • 【Python其他生成随机字符串的方法】
  • 《特征工程:自动化浪潮下的坚守与变革》
  • “AI智慧教学系统:开启个性化教育新时代