Qt第二课----信号和槽

news2024/11/15 17:43:32

作者前言

🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂
​🎂 作者介绍: 🎂🎂
🎂 🎉🎉🎉🎉🎉🎉🎉 🎂
🎂作者id:老秦包你会, 🎂
简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂
喜欢学习C语言、C++和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂🎂🎂🎂🎂🎂🎂
🎂个人主页::小小页面🎂
🎂gitee页面:秦大大🎂
🎂🎂🎂🎂🎂🎂🎂🎂
🎂 一个爱分享的小博主 欢迎小可爱们前来借鉴🎂


Qt

  • **作者前言**
  • 打印hello world
  • QT的编码格式
  • 使用编辑框进行输出hello wrold
  • 点击按钮
  • 信号和槽
    • 信号
    • 使用
    • 自定义信号
    • 自定义槽
    • 带参数的信号和槽
  • 窗口坐标体系
  • Q_OBJECT的介绍
  • 信号和槽的连接方式
  • 信号和槽 的断开
  • 总结

打印hello world

第一种方法,
在ui文件里面进行编辑
在这里插入图片描述
输入内容,然后运行文件,可以打印出来

第二种方法可以写c++代码进行运行出来
这里需要包含QLabel头文件, 这个头文件是之前Qt用的头文件风格
就好比19989年的c++98规定统一使用#include代替#include<stdio.h>头文件
还需要注意的是: 在Qt中,有自己的一套轮子,
QString、 QVector、QList 这些是Qt代码中常见的类型,一一对应的就是C++的string 、vector、list等类型
在这里插入图片描述

 QLabel *labe = new QLabel(this);//推荐在堆上创建,给labe指定一个父节点
 labe->setText("Hello world");//

图中代码,调用了QLabel的方法,使其显示出来,setText的参数是一个Qstring
如图:
在这里插入图片描述
这个方法默认显示到左上角,
观察代码,可以发现没有释放空间,会造成内存泄漏,这是潜意识,
但是是不会内存泄漏的,因为是把这个对象挂到了对象树上了
在这里插入图片描述
使用对象树,把内容组织起来,在合适的时候统一释放(窗口关闭时),但是如果挂在树上的对象提前销毁了,就会导致对应的的控件在界面上不存在了
如图:
在这里插入图片描述
所以说,labe对象会随对象树释放
我们也可以写一个类来进行观察,继承这个QLabel这个内置类,
在这里插入图片描述
.h

#include<QLabel>

class mylabel : public QLabel
{
public:
    mylabel(QWidget* parent);
    ~mylabel();

};

.cpp

#include<QDebug>
mylabel::mylabel(QWidget* parent)
    :QLabel(parent)
{

}

mylabel::~mylabel()
{
   qDebug()<< "释放了";//字符的编码格式和这个文件的编码格式一样
   //终端的编码格式不一样
   //
}

在构造函数中,必须指定父类,这样才能挂在对象树上,否则的话,只能自己手动的进行delete了

回归到原来问题上去,

QT的编码格式

在qt中,我们使用std::cout打印输出就会出现编码格式错误,
例如:

在这里插入图片描述

所以qt有自己的处理工具,或是使用Qstring类型
我们需要包含头文件<QDebug>,使用qDebug()来打印输出,

在这里插入图片描述qDebug()是一个宏,里面封装了一个QDebug对象,所以使用qDebug()相当于std::cout
需要注意是windos不要使用cout, 但是Linux可以,因为Linux的编码格式是utf-8,cpp的文件的编码格式也是utf-8

使用编辑框进行输出hello wrold

上面在程序面板中简单 输出了hello wrold, 这次我们来试试编辑框 QLineEdit,在设计中也可以通过ui文件进行设计,

bfd897d17.png)

在这里插入图片描述
接下来我们使用c++的纯代码来进行实现
还是一样的道理,使用啥控件就导入对应控件的名字(头文件), 导入#include<QLineEdit>
如图:

在这里插入图片描述
代码的写法还是一样的, 控件对象初始化一定要指明父类(父节点),

点击按钮

除了上面的方法,我们也可以通过点击按钮在程序面板中输出
这里需要我们导入头文件#include<QPushButton>

QPushButton * qbutton = new QPushButton(this);
qbutton->setText("hell world");

如图:
在这里插入图片描述

这个按钮点击是没有效果的,需要建立一个点击操作,这就涉及到信号和槽了

信号和槽

在Qt中,⽤户和控件的每次交互过程称为⼀个事件。⽐如"⽤⼾点击按钮"是⼀个事件,"⽤户关闭窗⼝"也是⼀个事件。每个事件都会发出⼀个信号,例如⽤⼾点击按钮会发出"按钮被点击"的信号,⽤⼾关闭窗⼝会发出"窗口被关闭"的信号,而在Qt中,对信号做出的响应动作就称之为槽

注意:信号的本质就是事件

槽的本质
槽(Slot)就是对信号响应的函数。槽就是⼀个函数,与⼀般的C++函数是⼀样的,可以定义在类的任何位置(public、protected或private),可以具有任何参数,可以被重载,也可以被直接调⽤(但是不能有默认参数)。槽函数与⼀般的函数不同的是:槽函数可以与⼀个信号关联,当信号被发射时,关联的槽函数被⾃动执⾏

说明
(1)信号和槽机制底层是通过函数间的相互调⽤实现的。每个信号都可以⽤函数来表⽰,称为信号函数;每个槽也可以⽤函数表⽰,称为槽函数。例如:"按钮被按下"这个信号可以⽤clicked()函数表⽰,"窗⼝关闭"这个槽可以⽤close()函数表⽰,假如使⽤信号和槽机制实现:"点击按钮会关闭窗⼝"的功能,其实就是clicked()函数调⽤close()函数的效果。
(2)信号函数和槽函数通常位于某个类中,和普通的成员函数相⽐,它们的特别之处在于:
• 信号函数⽤ signals关键字修饰,槽函数⽤public slots、protected slots或者private slots修饰。signals和slots是Qt在C++的基础上扩展的关键字,专⻔⽤来指明信号函数和槽函数;
• 信号函数只需要声明,不需要定义(实现),⽽槽函数需要定义(实现)

信号

在Linux中,进程的通讯方式是信号, signal,
谁发出来的,啥类型的信号, 怎么处理,
而在Qt中也有自己的信号,
涉及到三个要素
简单的理解的就是, 信号源、 信号类型, 处理方式(槽, connect的使用)

使用

在Qt中Qobject类中提供一个静态函数connet(),该函数专⻔⽤来关联指定的信号函数和槽函数
connect() 函数原型:

bool QObject::connect(const QObject *sender, 
const char *signal, 
const QObject *receiver,
 const char *method, 
 Qt::ConnectionType type = Qt::AutoConnection);

sender:信号的发送者;

signal:发送的信号(信号函数);传入函数指针

receiver:信号的接收者;

method:接收信号的槽函数;传入函数指针
type
= Qt::AutoConnection )

type:⽤于指定关联⽅式,默认的关联⽅式为Qt::AutoConnection,通常不需要⼿动设定。
在这里插入图片描述
这写了两个,从图中可以看出,qbutton是new出来的, pushButton是ui文件通过qmake生成的,
这个变量名我们是可以控制的,如果要更改的话,
如图:

在这里插入图片描述
qmake会根据ui文件的objectName对应的值,生成的变量名(唯一),我们也可以更改这个值,
我们这个值修改为puBu
如图:
在这里插入图片描述

需要注意的是:&QPushButton::clicked 是函数指针,
代码:

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    ,qbutton(new QPushButton(this))
{
    ui->setupUi(this);
    /*QLineEdit* qlineedit = new QLineEdit(this);
    qlineedit->setText("hello world");*/ // 单编辑框
    qbutton->setText("hell world");
    connect(qbutton,&QPushButton::clicked,this, &Widget::funtion);
    connect(ui->puBu,&QPushButton::clicked,this, &Widget::funtion);
}
void Widget:: funtion()
{

    qDebug() << "点击成功";
    if(ui->puBu->text()==QString("点击"))
    {
        ui->puBu->setText("成功点击");
    }
    else{
        ui->puBu->setText("点击");
    }

}

.h

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
   void funtion();
private:
    Ui::Widget *ui;
    QPushButton * qbutton;
};

看到这里, 很多人会迷惑,为啥在qt中,会使用不同的类型的指针进行传参,在c++中不能这样做的,
这是因为在以前的Qt版本中, connect传参需要传入宏的, 分别是SIGNAL和SLOT,
写法如下:

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

这两个宏的作用就是把函数指针类型转换成char*
而在QT5之后,就增加了泛型编程,也就是函数模板,
在这里插入图片描述

自定义信号

信号本质就是事件, 也就是一个“函数”,但是信号是一个特殊的函数, 程序员只要声明这个函数就行,至于函数的定义,是qt在编译的过程自动生成的(生成过程,程序员无法干预)

需要注意的是: 信号函数的返回值必须是void, 也没有形参都可以,重载函数也可以
在qt中有关键字signals:这个是c++没有的
至于怎么定义的函数, 是qmake在调用一些工具的时候,扫描到signal的时候,就会根据函数声明写出一个函数定义,
下面我们先声明一个信号函数,然后使用connect把信号和槽建立连接
在这里插入图片描述
然后我们运行起来, 就会发现。我们该怎么触发信号, 前面我们使用内置的点击可以触发信号,但是现在我们自定义信号, 没有这样的功能 这里Qt就引入了emit关键字, 使用这个关键字触发我们声明的信号函数

emit this->myclicked();

如图:
在这里插入图片描述
在Qt5中不写这个emit也可以

自定义槽

顾名思义,简单的理解就是一个函数的声明加定义,所以说当我们要定义一个槽函数需要按照Qt的写法进行,
槽函数写法1
在Qt中有c++中没有的关键字,为了区分普通函数和槽函数,qt增加了如下关键字

public slots:
protected slots;
private slots

槽函数定义和声明在其中,这样可以一目了样,就算不写在其中,也是可以的,这个要看程序员怎么写
槽函数写法2
除了上面的纯代码方式,还可以在ui文件进行
如图:

点击进行就会看到如下:
在这里插入图片描述
然后选择好信号就会生成对应的槽函数
在这里插入图片描述
然后我们只需要函数里面写我们的内容就行,
当我们运行的时候就会发现, qt文件中没有使用connect,而生成的ui_widget.h的头文件也没有,
这是因为,在QT中,信号和槽的链接不局限于使用connect, 还可以通过函数名的方式来链接
而生成的函数名字也是有讲究的,如图:
在这里插入图片描述
我们知道QPushButton有clicked这个函数,如果我们当名字更改了就会报错,
当我们更改后,
在这里插入图片描述

就会发现,输出的那里有一个函数名字叫做connectSlotsByName,这个对应着头文件ui_widget.h
在这里插入图片描述
当调用这个函数的时候,就会调用对应的函数名链接的规则,进行信号和槽的链接, 如果这个函数(connectSlotsByName)没有调用, 哪怕在Qt文件中没有更改函数名,也会报错,

总结:
如果我们时使用图形化工具创建控件的话,就使用函数名链接规则进行信号和槽的连接,
如果是纯代码的方式来创建控件的话,要使用connect来,因为我们没有调用connectSlotsByName这个函数

带参数的信号和槽

前面我们自定义或者内置的类的成员函数,都是没有参数的,如果要想写一个带有参数的信号函数,对应的槽函数也要带参数, 并且参数类型要一致,个数不一致也可以,信号函数参数个数 >= 槽函数参数个数
下面我写了一段代码

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    btn = new QPushButton("点击",this);
    connect(btn, &QPushButton::clicked, this,&Widget::HandBtn);
    connect(this, &Widget::myclicked, this, &Widget::handmyclicked);

}

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

void Widget::handmyclicked(const QString& ch)
{
    this->setWindowTitle(ch);
}

void Widget::HandBtn()
{
    btn->move(200,300);
    emit this->myclicked("无敌大厂");
}

大致思路:
在这里插入图片描述

窗口坐标体系

前面我们使用代码写出来的,都是默认在程序面板的左上角显示的,而在qt中的
坐标体系:以左上⻆为原点(0,0),X向右增加,Y向下增加。
在这里插入图片描述
在qt中,给某个控件设置位置的时候,相对于的坐标原点,就是父窗口的左上角
在这里插入图片描述
前面我们简单的理解了对象树, QPushButton作为Qwidget的子节点,对应的坐标原点就是QWidget框的左上角
当我们运行起来就会默认在qwidget的左上角,
在这里插入图片描述
我们可以使用move函数

void move(int x, int y);

就会在(x,y)处开始显示,这个是相对于Qwidget这个父框的
如图:
在这里插入图片描述

我们也可以给Qwidget这个窗口进行设置,

Q_OBJECT的介绍

前面我们知道,如果一个类中要定义和使用信号和槽(或者定义和声明信号和槽),就需要类开始的地方写入宏 Q_OBJECT,否则就会报错

信号和槽的连接方式

在大部分的GUI网页开发中,主要形式不是使用connect这样的形式,(一对一形式)

funtion handle()
{
.....
}
button.onclick = handle;

只要点击就会触发函数, 这种方式有很多, 但是在Qt中, 搞出connect这样的方式,是为了解决信号和槽的耦合, 也就是实现处理 用户的操作控件和处理用户的操作的逻辑,(一个控件需要产生不同的效果),也叫解耦合
还有就是实现一个信号连接多个槽函数,或者一个槽函数连接多个信号,
总结: 在qt中信号和槽的连接有一对一. 一对多以及多对多的方式

信号和槽 的断开

关键字: disconnect
代码如下:


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(ui->pushButton1, &QPushButton::clicked, this, &Widget::Myslot1);
     connect(ui->pushButton2, &QPushButton::clicked, this, &Widget::Myslot2);
}

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

void Widget::Myslot1()
{
    qDebug()<< "Myslot1";
    this->setWindowTitle("东东");
}
void Widget::Myslot2()
{
    qDebug()<< "Myslot2";
    //断开
    disconnect(ui->pushButton1, &QPushButton::clicked, this, &Widget::Myslot1);
    //重新连接
    connect(ui->pushButton1, &QPushButton::clicked, this, &Widget::Myslot3);
}
void Widget::Myslot3()
{
    qDebug()<< "Myslot3";
    this->setWindowTitle("喜喜");
}

如图:
在这里插入图片描述
disconnect一般不怎么使用,主动断开连接,一般情况下是连接其他的槽函数,
除了上面这样声明和定义槽函数, 还可以使用lambda表达式
在这里插入图片描述
但是需要注意到是Qt中的lambda表达式支持是在c++11的基础上的,Qt5之后的版本,如果是Qt5之前的版本,就需要在.pro文件中更改一下,如图:
在这里插入图片描述

总结

Linux中的信号和Qt中的信号有很多相似点,

  1. 信号源
    2)信号类型
    3)信号的处理方式

信号和槽的连接和使用
connect的使用和disconnect的使用

自定义信号和槽函数
Q_OBJECT宏
lambda表达式

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

带你速通C语言——静态变量(14)

使用静态变量 (static) 在 C 语言中是管理函数内部状态或跨函数调用保持数据的一种有效方式。理解静态变量如何工作可以帮助你编写更加复杂和可控的程序。 1.静态变量的特性 静态变量有几个关键特性&#xff1a; 持久性&#xff1a;静态变量在函数多次调用之间保持其值。它们…

霍尼韦尔护眼大路灯怎么样?书客、月影、霍尼韦尔实测数据大揭秘

霍尼韦尔大路灯怎么样&#xff1f;目前市面上的大路灯外观几乎都大同小异&#xff0c;但很多品牌在宣传方面做的很牛&#xff0c;消费者在拿到手后的体验却是大打折扣&#xff0c;跟官方宣传的真的是一个天一个地&#xff0c;相差太大。作为一个测评博主&#xff0c;很多人问我…

elasticsearch整合java使用创建索引、指定索引映射、操作添加文档、删除文档、更新文档、批量操作

前言&#xff1a; elasticsearch的整合流程可以参考&#xff1a;Elasticsearch7.15版本后新版本的接入-CSDN博客 索引 1.创建索引 Testpublic void contextLoads() throws IOException {ElasticsearchClient elasticsearchClient elasticSearchConfig.esRestClient();bool…

【Qt】表单布局QFormLayout

表单布局QFormLayout Qt 还提供了 QFormLayout , 属于是 QGridLayout 的特殊情况, 专⻔⽤于实现两列表单的布局. 这种表单布局多⽤于让⽤⼾填写信息的场景. 左侧列为提⽰, 右侧列为输⼊框 例子&#xff1a;使用QFormLayout创建表单 &#xff08;1&#xff09;设置三个label、…

数据分析及应用:如何对试卷得分做min-max归一化处理?

目录 0 问题描述 1 数据准备 2 问题分析 3 小结 0 问题描述 现有试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间): 试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时…

强者和弱者的区别体现在面对失败上

面对成功&#xff0c;面对日常&#xff0c;每一个人都是谦谦君子温文尔雅&#xff0c;谈论困难挫折&#xff0c;不屑一顾。 这是他们的真实面目吗&#xff1f; 有的是真的&#xff0c;有的是假的。 强者视失败为磨砺意志的砥石&#xff0c;他们勇于承认不足&#xff0c;积极寻…

物联网架构之CDH集群部署

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

中国各地区-交通运输-电信业务总量(1999-2020年)

电信业务总量是指以货币形式表示的电信企业为社会提供的各类电信服务的总数量&#xff0c;包含了各类电信业务&#xff0c;如固定电话、移动电话、数据通信、互联网接入等。 1999-2020年 中国各地区-交通运输-电信业务总量 指标 年份、地区、交通运输-电信业务总量(亿元)。 …

2024年8月29日(harbor似有仓库管理,Docker-compose容器编排)

一、harbor私有仓库管理 yum -y install epel-release yum -y install python2-pip pip install --upgrade pip pip list pip 8x pip install --upgrade pip pip install --upgrade pip20.3 -i https://mirrors.aliyun.com/pypi/simple pip list pip install docker-compo…

基于my Batis优化图书管理系统(总)

1.准备工作 1.1 数据库表设计 -- 创建数据库 DROP DATABASE IF EXISTS book_manage;CREATE DATABASE book_manage DEFAULT CHARACTER SET utf8mb4; use book_manage;-- 用户表 DROP TABLE IF EXISTS user_info; CREATE TABLE user_info (id INT NOT NULL AUTO_INCREMENT,use…

网站建设完成后, 功能性网站如何做seo

功能性网站的SEO优化关注于提高网站在搜索引擎中的排名&#xff0c;从而吸引更多用户并提升用户体验。以下是功能性网站SEO的详细解析&#xff1a; 关键词研究与布局 目标受众分析&#xff1a;了解目标受众的搜索习惯和需求&#xff0c;确定适合的关键词。使用工具如Google Ke…

反弹shell流量分析与检测

常用的隧道技术&#xff1a; 网络层&#xff1a;ipv6、Icmp、gre IPv6隧道&#xff1a;将ipv6报文放入ipv4作为载体进行传输&#xff0c;工具&#xff1a;socat、6tunnel ICMP隧道&#xff1a;将数据放入ping包中进行传输&#xff0c;工具&#xff1a;icmpsh、PingTunnel G…

日本麻将入门(二):牌效率【基础】

基础牌效率 引入 日麻&#xff0c;又称立直麻将。日麻的水平本质上与你是否会立直有很大关系&#xff08;参见常用役种&#xff1a;立直&#xff1a;优点&#xff09;&#xff0c;但立直最大的缺点就是不能副露&#xff0c;导致我们只能通过自己的摸切来完成听牌形的组成。在…

20. 筛选dataframe

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 筛选条件 基本筛选 要筛选DataFrame&#xff0c;首先需要了解筛选条件。Pandas提供了多种筛选条件&#xff0c;包括等于&#xff08;&#xff09;、不等于&#xff08;&#xff01;&#xff09;、大于&#xff08;…

Leetcode Day14排序算法

动态git可以看 :https://leetcode.cn/problems/sort-an-array/solutions/179370/python-shi-xian-de-shi-da-jing-dian-pai-xu-suan-fa/ 选择排序 def selection_sort(nums):n len(nums)for i in range(n):for j in range(i, n):if nums[i] > nums[j]:nums[i], nums[j] …

05.整合Axios+MockJs

1. 前言 作为前后端分离的项目&#xff0c;必不可少的当然是发请求向后端拿数据了&#xff0c; 但是不可能每次等到接口完成我们才开始开发前端&#xff0c;所以使用 mock.js 先模拟后端接口&#xff0c;等后端接口开发完成后&#xff0c;可以无缝衔接&#xff0c;直接替换为真…

EmguCV学习笔记 VB.Net 7.2 特征点检测

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。 教程VB.net版本请访问…

(24)(24.6) 基于OSD的参数菜单

文章目录 前言 1 Copter默认屏幕 2 Plane默认屏幕 3 实例 前言 这允许使用 ArduPilot 机载 OSD 和 RC 发射机的杆输入设置和调整参数。还有两个额外的 OSD 屏幕可用&#xff08;OSD5 和 OSD6&#xff09;&#xff0c;每个屏幕有 9 个“插槽”来保存参数。屏幕首先显示一组…

taro ui 小程序at-calendar日历组件自定义样式+选择范围日历崩溃处理

taro ui 日历文档 目录 单选标记时间&#xff1a; 效果&#xff1a; template&#xff1a; data&#xff1a; methods: 日历--范围选择&#xff1a; 效果&#xff1a; template&#xff1a; data&#xff1a; methods&#xff1a; 日历--间隔多选&#xff1a;利用标…

详细分析python中QRCode生成二维码的基本知识(附Demo)

目录 前言1. 基本知识2. Demo3. 彩蛋3.1 文件路径3.2 Image.LANCZOS 前言 以下主要利用python中的QRCode来生成二维码的基本知识 1. 基本知识 简单易用&#xff0c;并且可以生成高质量的二维码图像 支持多种自定义设置&#xff0c;例如二维码的大小、边框、容错级别、颜色等…