QT C++(信号与槽函数,自定义信号和槽函数)

server/2024/10/20 6:03:41/

文章目录

  • 1. QT信号与槽函数
  • 2. QT自定义信号和槽函数

1. QT信号与槽函数

QT信号关键要素:

  1. 信号源:那个控件发送的信号
  2. 信号类型:用户进行不同的操作,就可能触发不同的信号。
    eg:点击按钮,移动鼠标等
  3. 信号处理方式:使用槽函数(slot)将信号与对应的信号处理函数关联起来(回调函数)

在QT中使用connect函数关联信号和信号处理函数(槽函数),这个函数是QObject类(基类)的静态成员函数

connect函数原型

 static QMetaObject::Connection connect(const QObject *sender, const char *signal,const QObject *receiver, const char *member, Qt::ConnectionType type= Qt::AutoConnection);
  • sender:当前信号是那个控件发送的(信号源)
  • singal:信号的类型,发送的是那种信号
  • receiver+member:信号如何处理
    • receiver:那个对象负责处理(控件)
    • member:这个对象怎么处理(函数)
  • type:有默认值,一般不填写

QT信号也是QT对象,内部提供一些成员函数,使用时需要注意发送信号和相应的控件符合。

各种控件的信号可以看QT文档

上述的函数声明,是旧版本的QT,旧版本的QT给信号参数传参需要搭配一个SIGNAL宏
给槽函数传参需要搭配一个SLOT宏connect(button,SIGNAL(&QPushButton::clicked),this,SLOT(&QWidget::close));

eg:

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton*button=new QPushButton(this);button->setText("关闭");button->move(200,200);//点击关闭信号,this指的Widget,通过Widget来响应这个信号,&QWidget::close是QT内置的槽函数,负责控件关闭connect(button,&QPushButton::clicked,this,&QWidget::close);
}Widget::~Widget()
{delete ui;
}

2. QT自定义信号和槽函数

自定义槽函数:

方式一:手动定义函数

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton*button=new QPushButton(this);button->setText("按钮");button->move(200,200);connect(button,&QPushButton::clicked,this,&Widget::handerClick);
}Widget::~Widget()
{delete ui;
}void Widget::handerClick()
{//按下按钮,设置窗口标题this->setWindowTitle("按钮按下");qDebug()<<this->windowTitle();
}

方法二:通过ui界面生成槽函数
在这里插入图片描述
这个窗口就是QPushButton控件提供的所有信号
在这里插入图片描述

此时这个函数自动会绑定这个按钮的信号(通过函数名称来绑定,函数名为on+按钮的objectname+信号名称)egon_myButton_clicked,当函数名符合上述规则,QT会对响应控件的信号自动进行绑定(connectSlotsByName函数)
在这里插入图片描述

自定义信号:实际开发中比较少,QT内置信号基本已经覆盖控件所有操作,自定义信号一般需要程序员手动发送(emit关键字)

QT信号本质上也是函数(特殊函数,只有函数声明,并且将其声明成QT信号即可,QT编译自动生成这个信号函数)信号函数的返回值为void,有无参数都可以。

eg:

//.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_myButton_clicked();private:Ui::Widget *ui;//自定义信号,QT扩展的关键字,在qmake扫描带这个关键字后会生成具体代码
signals:void mySignals();
public:void handMySignals();
};
#endif // WIDGET_H//.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//关联自定义信号connect(this,&Widget::mySignals,this,&Widget::handMySignals);//初始化时发送自定义信号emit mySignals();
}Widget::~Widget()
{delete ui;
}void Widget::handMySignals()
{this->setWindowTitle("自定义信号");
}

带参数的信号和槽函数

当信号带有参数时,槽的参数必须和信号一致,此时发射信号时就可以给这个信号函数传递参数,与之对应的参数就会被传递给槽函数

//.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECT //Q_OBJECT宏:在QT中让某个类能够使用信号槽机制,必须要在类最开始的地方声明这个宏。public:Widget(QWidget *parent = nullptr);~Widget();//自定义信号,QT扩展的关键字,在qmake扫描带这个关键字后会生成具体代码
signals:void mySignals(const QString&);
public:void handMySignals(const QString&);
};
#endif // WIDGET_H//.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//关联自定义信号connect(this,&Widget::mySignals,this,&Widget::handMySignals);//初始化时发送自定义信号emit mySignals("带参自定义信号");
}Widget::~Widget()
{delete ui;
}
void Widget::handMySignals(const QString&text)
{this->setWindowTitle(text);
}

注意:当信号函数参数个数超过了槽函数参数个数,代码可以正常运行,信号多余的参数槽函数接受不到。反之报错

这里这样设计的原因是:信号与槽函数绑定不是一对一的,一个槽函数可能绑定多个信号,如果严格要求信号函数和槽函数参数一致,那么同一个槽函数有些信号无法绑定。使用这样的规则,信号和槽的绑定更加灵活,这样更多的信号就可以绑定到这个槽函数了。

Q_OBJECT宏:在QT中让某个类能够使用信号槽机制,必须要在类最开始的地方声明这个宏。
在这里插入图片描述

QT信号和槽机制的优点:

  1. 解耦合:触发用户的控件和处理用户的操作逻辑解耦合
  2. 一个信号可以绑定多个槽函数,一个槽函数也可以绑定多个信号(多对多,关联表)

此外可以使用disconnect函数断开信号和槽函数的连接
eg:

void Widget::on_pushButton_clicked()
{this->setWindowTitle("修改窗口标题");
}void Widget::on_pushButton_2_clicked()
{//断开原来按钮的槽函数disconnect(ui->pushButton,&QPushButton::clicked,this,&Widget::on_pushButton_clicked);qDebug()<<"重新绑定槽函数";//重新绑定信号槽connect(ui->pushButton,&QPushButton::clicked,this,&Widget::handclick);
}void Widget::handclick()
{this->setWindowTitle("重新修改窗口标题");
}

此外,在定义槽函数时也可以使用lambda表达式,其本质就是匿名函数,常常用于回调函数

eg:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton*button=new QPushButton(this);button->setText("按钮");int* times=new int(1); //这里必须new 因为这是在构造函数中connect的,设计变量声明周期问题,new出的变量必须手动释放,变相提高了声明周期,使得connect函数捕获times指针解引用不会报错//lambda作为回调函数connect(button,&QPushButton::clicked,this,[=](){qDebug()<<"lambda回调函数";//点击按钮移动按钮button->move(10*(*times),10*(*times));*times+=1;});emit signals1();emit signals2();}

http://www.ppmy.cn/server/18142.html

相关文章

基于 SpringCloud 的在线交易平台商城的设计与实现

摘 要 随着互联网的快速发展&#xff0c;人们对商品经济的消费和思考不再停留在传统 的经济模式上&#xff0c;网上购物商城是企业与企业进行、企业与消费者进行电子商 务交易的一个很好平台。网上购物商城极大地降低了企业商家的交易成本&#xff0c; 缩短企业供应链周期&…

layabox手游全面屏、ipad屏幕适配方案

1设置 手游平台在项目设置中&#xff0c;场景适配模式选择”固定宽模式 fixedwidth“&#xff0c;设计宽度以全面屏比例为主&#xff0c;我这里设置的设计宽高为640 * 1386 2代码和场景 laya的UI面板有三种类型&#xff0c;分别是Scene、View和Dialog 1&#xff09;Scene和V…

leetcode2418.按身高排序

题目描述&#xff1a; 给你一个字符串数组 names &#xff0c;和一个由 互不相同 的正整数组成的数组 heights 。两个数组的长度均为 n 。 对于每个下标 i&#xff0c;names[i] 和 heights[i] 表示第 i 个人的名字和身高。 请按身高 降序 顺序返回对应的名字数组 names 。 …

信号量和互斥锁的区别

信号量和互斥锁都是用于多线程编程中的同步机制&#xff0c;但它们在用途和操作上存在一些差异。具体分析如下&#xff1a; 用途&#xff1a;互斥锁&#xff08;Mutex&#xff09;主要用于实现线程间的互斥&#xff0c;即确保同一时刻只有一个线程能够访问共享资源或临界区。它…

LeetCode39:组合总和

题目描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates 中的 同一个 数字可以 无限制重复被…

JavaScript-Vue入门

本文主要测分享Vue的一些基础 Vue简介 Vue.js 是一个构建数据驱动的 web 界面的渐进式框架。它的主要目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。 下是一些 Vue 的主要特点和概念&#xff1a; 1. 响应式数据绑定&#xff1a;Vue 使用基于 HTML 的模板语法…

【MySQL】DML

1、DML简介 DML&#xff08;Data Manipulation Language、数据操作语言&#xff09;&#xff0c;用于添加、删除、更新和查询数据库记录&#xff0c;并检查数据完整性。 2. 添加数据 2.1 使用关键字 使用 INSERT 语句向表中插入数据。使用 VALUES语句添加 2.2 使用情况 2.2…

【C++】封装、继承和多态

引言 在现代软件开发中&#xff0c;面向对象编程&#xff08;Object Oriented Programming&#xff09;已经成为一种广泛应用的编程范式。C作为一种支持面向对象编程的语言&#xff0c;在封装、继承和多态方面提供了强大的特性。本文将介绍C中的封装、继承和多态概念&#xff…