Qt信号与槽

我们在使用Qt的时候,不使用Qt Designer 的方式进行开发,使用ui文件,信号与槽的连接方式是生成代码之后才能在setupUi函数里才能看到,或者需要进入Ui设计器里的信号槽模式里才能看到信号槽的连接。所以我们最好使用代码绘制界面。

一.Qt信号与槽机制

信号(Signal)就是在特定情况下被发射的事件,槽(Slot)就是对信号响应的函数。槽函数与一般函数不一样的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。

信号与槽关联是用QObject::connect() 函数实现的,其基本格式是:

QObject::connect(sender,SIGNAL(signal()),recevier,SLOT(slot));

connect()是QObject类的一个静态函数而QObject是所有Qt类的基类,在实际调用时可以忽略前面的限定符,所以可以直接写为:

connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));

其中,sender 是发射信号的对象的名称,signal() 是信号名称。信号可以看做是特殊的函数,需要带括号,有参数时还需要指明参数。receiver 是接收信号的对象名称,slot() 是槽函数 的名称,需要带括号,有参数时还需要指明参数。

当信号和槽函数带有参数时,在 connect()函数里,要写明参数的类型,但可以不写参数名称。

一个信号可以连接另外一个信号(说明了 connect 万物皆可连,非常好用!),例如:

connect(pushButton,SIGNAL(objectNameChanged(QString)),this, SIGNAL(windowTitelChanged(QString)));

这样,当一个信号发射时,也会发射另外一个信号,实现某些特殊的功能。

严格的情况下,信号与槽的参数个数和类型需要一致,至少信号的参数不能少于槽的参数。 如果不匹配,会出现编译错误或运行错误。

在使用信号与槽的类中,必须在类的定义中加入宏 Q_OBJECT(特别重要)。

当一个信号被发射时,与其关联的槽函数通常被立即执行,就像正常调用一个函数一样。 只有当信号关联的所有槽函数执行完毕后,才会执行发射信号处后面的代码。

总结如下图,可以看到发送者与发送的信号是在一起的,接收者与接收的信号/槽是在一起 的。它们不能在 connect()方法里写乱顺序!由发送者发送出信号到接收者用信号/槽接收。

信号槽连接的方法已经讲解过了,接下来讲解一下断开连接的方法,使用disconnect()。

bool QObject::disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)

信号与槽机制是 Qt GUI 编程的基础,使用信号与槽机制可以比较容易地将信号与响应代码关联起来。

二. 如何在项目里创建信号

信号只需声明,无需定义。所以我们只需要在 mianwindow.h 里声明信号即可。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
/*引入 QPushButton */
#include <QPushButton>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

signals:
    /* 声明一个信号,只需声明,无需定义 */
    void pushButtonTextChanged();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

三. 如何在项目中创建槽

创建槽的方法也很简单,也是直接在 mianwindow.h 里直接声明槽,在 mianwindow.cpp 里 实现槽的定义,声明槽必须写槽的定义(定义指函数体的实现),否则编译器编译时将会报错。

槽有以下特点:

  1. 槽可以是任何成员函数,普通全局函数,静态函数

  2. 槽函数和信号的参数和返回值要一致

根据上面的槽特点,由于我们声明了信号 void pushButtonTextChanged(); 所以我们声明的槽函数必须是无返回值类型 void,和无需参数。所以声明槽的代码如下。此外 我们还声明一个 QPushButton 对象 pushButton。对象 pushButton 可以写成简写 btn。这个根据个 人习惯即可!简写的名称建议不要让人看不懂即可!同时还声明一个按钮点击的槽。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
/*引入 QPushButton */
#include <QPushButton>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

signals:
    /* 声明一个信号,只需声明,无需定义 */
    void pushButtonTextChanged();

public slots:   
    /*声明一个槽函数*/
    void changeButtonText();
    /*声明按钮点击的槽函数*/
    void pushButtonClicked();
private:
    /* 声明一个对象 pushButton 也可以是btn,易于读懂就行 */
    QPushButton *pushButton;
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

在 mainwindow.cpp 里实现 声 明 的 槽 函 数 void changeButtonText(); 和 void pushButtonClicked();。同时还实例化了 pushButton 对象。代码如下。

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

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow) //new一个UI中的MainWindow,这里是一种初始化成员的方法
{
    //ui->setupUi(this);//这句话是进行界面初始化,将this作为参数传到setupUi里,ui界面
    //文件的对象会以this为父对象,所有子对象将显示在MainWindow里,我们要想使用ui里的对象
    //必须将代码写在ui->setUi(this)这句话之后,因为ui->setupUi(this)会先初始化里面的对象,只有初始化
    //里面的对象我们才能使用这个对象

    /* 设置窗体的宽为 800,高为 480 */
    this->resize(800,480);
    /* 实例化 pushButton 对象 */
    pushButton = new QPushButton(this);
    /* 调用 setText()方法设定按钮的文本 */
    pushButton->setText("我是一个按钮");
}

MainWindow::~MainWindow()
{
    delete ui;
}
/* 实现按钮点击槽函数 */
void MainWindow::pushButtonClicked()
{
    /* 使用 emit 发送信号 */
    emit pushButtonTextChanged();
}
/* 实现按钮文本改变的槽函数 */
void MainWindow::changeButtonText()
{
    /* 在槽函数里改变按钮的文本 */
   pushButton->setText("被点击了!"); 
}

四. 如何在项目中连接信号与槽

信号槽连接的代码如下

connect(pushButton, SIGNAL(clicked()), this, SLOT(pushButtonClicked()));
connect(this,SIGNAL(pushButtonTextChanged()), this, SLOT(changeButtonText()));

注意,发送信号的对象,和接收的信号的对象。因为我们 pushButtonClicked()是本类里定 义的槽,所以用 this 来接收。同理pushButtonTextChanged()也是本类定义的信号。所以发送 者写成 this。changeButtonText()也是本类的槽函数,所以接收槽的对象也是 this。

在 mainwindow.cpp 中信号槽连接的代码如下

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

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow) //new一个UI中的MainWindow,这里是一种初始化成员的方法
{
    //ui->setupUi(this);//这句话是进行界面初始化,将this作为参数传到setupUi里,ui界面
    //文件的对象会以this为父对象,所有子对象将显示在MainWindow里,我们要想使用ui里的对象
    //必须将代码写在ui->setUi(this)这句话之后,因为ui->setupUi(this)会先初始化里面的对象,只有初始化
    //里面的对象我们才能使用这个对象

    /* 设置窗体的宽为 800,高为 480 */
    this->resize(800,480);
    /* 实例化 pushButton 对象 */
    pushButton = new QPushButton(this);
    /* 调用 setText()方法设定按钮的文本 */
    pushButton->setText("我是一个按钮");
    /* 信号与槽连接 */
    connect(pushButton, SIGNAL(clicked()), this,SLOT(pushButtonClicked()));
    connect(this, SIGNAL(pushButtonTextChanged()), this,SLOT(changeButtonText()));
}

MainWindow::~MainWindow()
{
    delete ui;
}
/* 实现按钮点击槽函数 */
void MainWindow::pushButtonClicked()
{
    /* 使用 emit 发送信号 */
    emit pushButtonTextChanged();
}
/* 实现按钮文本改变的槽函数 */
void MainWindow::changeButtonText()
{
    /* 在槽函数里改变按钮的文本 */
  pushButton->setText("被点击了!");
}

五. 学会使用 Qt 类的信号与槽

Qt里有大量的信号与槽,都是Qt自定义好的,那么我们该如何使用Qt信号与槽呢?

进入 QPushButton 的定义处,我们看到 QPushButton 不止 clicked 信号,还有其他信号,也 有 QPushButton 的槽函数(返回上一步按 Alt + 方向左键)。在这里我们只是简单的看了如何在 已知信号和槽里查找其他信号与槽。实际上在开发中我们经常需要使用 Qt 帮助文档来查看 Qt 定义的信号与槽。我们将在下一章里讲解 Qt 帮助文档的使用,帮助文档里面就有如何查看 Qt 的信号与槽等等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/538379.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CCD机器视觉在工业生产中起到什么作用?

CCD机器视觉尺寸测量是基于相对测量方法&#xff0c;通过可追溯性、放大校准、自动边缘提升和屏幕图像测量来计算实际尺寸。在精密测量中&#xff0c;放大倍数必须达到35倍或更高&#xff0c;才能达到微米级的精度。此时&#xff0c;视线宽度小于5mm。对于大于5mm的物体&#x…

游戏提示找不到steam_api64.dll,无法继续执行代码的解决方法

在我们日常沉浸在电脑世界中&#xff0c;尽情享受各类电子游戏带来的精彩与刺激时&#xff0c;偶尔会遭遇一些令人困扰的技术问题。这次&#xff0c;当您正全神贯注地启动心仪的游戏&#xff0c;期待着新一局冒险或竞技的开始&#xff0c;电脑屏幕上却冷不防地弹出一条警示信息…

--每周分享--

分享内容&#xff1a; 1.单链表的归并排序 2.一道有趣的思考题 分享细节&#xff1a; 单链表的归并排序 主要思想&#xff1a;递归 怎么理解&#xff1f;下面具体说明&#xff1a; 1.首先&#xff0c;我从整体的思考步骤说明&#xff1a;先分区&#xff0c;再排序&#…

游标的定义和类型

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 游标的基本概念 游标从字面上理解为游动的光标&#xff0c;可以使用 Excel 表格来想象游标的作用&#xff0c;游标指向每一行&#xff0c;通过游标访问每行数据。 在 Orac…

二维相位解包理论算法和软件【全文翻译- 菲林(Flynn)最小不连续性方法(4.5)】

4.5 菲林最小不连续性方法 在迄今为止对路径跟踪算法的讨论中,我们忽略了一种非常自然的方法,现在我们将对其进行描述。如果我们仔细观察图 4.42(a)中包裹相位数据中的条纹图案,就会发现 "条纹线 "或最亮像素和最暗像素之间的边界标志着从 0 到 2π 的过渡,它们…

【LAMMPS学习】八、基础知识(1.5) LAMMPS 库接口

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

react17中配置webpack:使用@代表src目录

在vue的项目中可以使用表示src目录&#xff0c;使用该符号表示绝对路径&#xff0c;那么在react中想要使用怎么办呢&#xff1f; 在react中使用表示src目录是需要在webpack中配置的&#xff0c;在核心模块node_modules-》react-scripts-》config-》webpack.config.js中搜索找到…

城市内涝与海绵城市规划设计中的水文水动力模拟

原文链接&#xff1a;城市内涝与海绵城市规划设计中的水文水动力模拟https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247601198&idx5&sn35b9e5e3961ea2f190f9742236a7217f&chksmfa820dc9cdf584df97633f64d19bdc3e5f7d1a5a85000c8f040e1953c51b9b39c87b5…

【Linux】Socket编程接口 | 实现简单的UDP网络程序

文章目录 一、预备知识理解源IP地址和目的IP地址理解源mac地址和目的mac地址认识端口号理解源端口号和目的端口号理解“端口号&#xff08;PORT&#xff09;”和“进程ID&#xff08;PID&#xff09;” 认识TCP和UDP协议TCP协议UDP协议 网络字节序为什么网络字节序采用的是大端…

华媒舍:7种方式,打造出旅游媒体套餐

现如今&#xff0c;伴随着旅游业发展与繁荣&#xff0c;更多旅游业发展从业人员越来越重视产品营销品牌基本建设&#xff0c;希望可以将自己的度假旅游产品和服务营销推广给更多的潜在用户。而建立一个优秀的旅游业发展媒体套餐内容品牌是吸引目标客户的重要步骤。下面我们就详…

6.3Python之字典的内置方法

1、创建字典 dict.fromkeys() &#xff1a;可将列表、元组、集合转为字典 knowledgeL [语文, 数学, 英语] scoresD1 dict.fromkeys(knowledgeL, 60) print(scoresD1) knowledgeT (Chinese, Math, English) scoresD2 dict.fromkeys(knowledgeT, 60) print(scoresD2) knowl…

用html写一个雨的特效

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>雨特效</title><link rel"stylesheet" href"./style.css"> </head> <body> <div id"wrap-textu…

一文掌握 React 开发中的 JavaScript 基础知识

前端开发中JavaScript是基石。在 React 开发中掌握掌握基础的 JavaScript 方法将有助于编写出更加高效、可维护的 React 应用程序。 在 React 开发中使用 ES6 语法可以带来更简洁、可读性更强、功能更丰富,以及更好性能和社区支持等诸多好处。这有助于提高开发效率,并构建出更…

Stable Diffusion——SDXL Turbo让 AI 出图速度提高10倍

摘要 在本研究中&#xff0c;我们提出了一种名为对抗扩散蒸馏&#xff08;ADD&#xff09;的创新训练技术&#xff0c;它能够在1至4步的采样过程中&#xff0c;高效地对大规模基础图像扩散模型进行处理&#xff0c;同时保持图像的高质量。该方法巧妙地结合了分数蒸馏技术&…

【企业场景】设计模式重点解析

设计模式 在平时的开发中&#xff0c;涉及到设计模式的有两块内容&#xff1a; 我们平时使用的框架&#xff08;比如spring、mybatis等&#xff09;我们自己开发业务使用的设计模式。 在平时的业务开发中&#xff0c;其实真正使用设计模式的场景并不多&#xff0c;虽然设计号…

企业业务遇到CC攻击,为何让人如此头疼。

随着互联网的普及和应用&#xff0c;网络安全已经成为人们越来越关注的一个问题。 随着网络信息化不断发展&#xff0c;用户对网站体验有着更高的要求&#xff0c;在网络时代&#xff0c;网站的稳定性至关重要&#xff0c;活跃在网络中的恶意攻击者惯用各类攻击手段破坏网站的稳…

C# Solidworks二次开发:几何公差IGot相关操作API详解

大家好&#xff0c;今天要介绍的是关于几何公差IGot相关操作的API。 几何公差之前没有讲过&#xff0c;具体API如下面所示&#xff1a; &#xff08;1&#xff09;第一个为GetText&#xff0c;这个API的含义为获取此几何公差的指定文本部分&#xff0c;下面是官方的具体解释&…

每日OJ题_01背包①_牛客DP41 【模板】01背包(滚动数组优化)

目录 牛客DP41 【模板】01背包 问题一解析 问题二解析 解析代码 滚动数组优化代码 牛客DP41 【模板】01背包 【模板】01背包_牛客题霸_牛客网 #include <iostream> using namespace std;int main() {int a, b;while (cin >> a >> b) { // 注意 while 处…

智慧污水井物联网远程监控案例

智慧污水井物联网远程监控案例 在当今数字化转型的浪潮中&#xff0c;智慧水务已成为城市基础设施建设的重要组成部分。其中&#xff0c;基于物联网技术的智慧污水井远程监控系统以其高效、精准、实时的特性&#xff0c;在提升污水处理效能、保障城市水环境安全、实现精细化管…

Jmeter安装与测试

一&#xff1a;JMeter简介&#xff1a; JMeter&#xff0c;一个100&#xff05;的纯Java桌面应用&#xff0c;由Apache组织的开放源代码项目&#xff0c;它是功能 和性能测试的工具。具有高可扩展性、支持Web(HTTP/HTTPS)、SOAP、FTP、JAVA 等多种协议的特点。 官方网站&#x…