Qt学习笔记第41到50讲

第41讲 UI美化遗留问题解决

如上图所示目前记事本的雏形已现,但是还是有待优化,比如右下角的拖动问题。

解决方法:

①首先修改了Widget类的构造函数。

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

下面开始逐步讲解,在Widget构造函数当中,我们首先初始化了成员变量:

 ui(new Ui::Widget)

这里为类的成员变量 ui 分配内存并进行初始化。ui 通常是一个指向特定用户界面类的指针,这个类是由 Qt 的 UI 设计工具生成的。通过初始化 ui,可以在后续的代码中访问和操作由设计师创建的用户界面元素。

然后设置父窗口和布局:

QWidget(parent)

调用父类 QWidget 的构造函数并传入 parent 参数。这使得当前创建的 Widget 实例能够与指定的父窗口建立关系。如果有父窗口,当父窗口被销毁时,子窗口也会被自动销毁,有助于管理窗口资源和层次结构。

ui->setupUi(this)

这个函数通常由 Qt 的 UI 设计工具生成的代码调用。它负责设置用户界面,将各种界面元素(如按钮、文本框等)与对应的成员变量关联起来,并根据设计设置初始状态和属性。

this->setLayout(ui->verticalLayout)

这一行是我们自己写的,将当前窗口的布局设置为 ui->verticalLayout。布局管理器用于自动管理窗口内的子部件的大小和位置。通过设置布局,可以确保界面元素在窗口大小变化时能够正确地调整位置和大小,提高用户界面的适应性。

ui->widgetBottom->setLayout(ui->horizontalLayout)

这一行也是我们自己写的,这里为特定的子部件 ui->widgetBottom 设置布局为 ui->horizontalLayout。这使得该子部件内的元素能够按照水平布局进行排列和调整。

②在UI底部添加两个弹簧控件;

左侧可拉伸,右侧选择fixed锁死长度。

第42讲 信号与槽的引入

基本概念

1. 信号 (Signals) :是由对象在特定事件发生时发出的消息。例如, QPushButton 有一个clicked() 信号,当用户点击按钮时发出。
2. (Slots) :是用来响应信号的方法。一个槽可以是任何函数,当其关联的信号被发出时,该槽函数将被调用。
3. 连接信号和槽 :使用 QObject::connect() 方法将信号连接到槽。当信号发出时,关联的槽函数
会自动执行。(PS:connect属于静态函数,通过“类名::函数名”可以直接使用。)

控件案例

下面我提供一个案例帮助大家理解。

①在主窗口放置了一个按键;

②切换到信号与槽的编辑器,点击绿色的+号增添一位信号发送者;

③双击“发送者”下面的单元格,一次选择发送者为pushButton,信号为click,接受者为MainWindow,槽选择为close;(达成的效果是按下按键后,组件发送信号给主窗口,主窗口关闭)

第43讲 信号与槽的四种代码实现方式

总览

使用QObject::connect

尝试在在构造函数内部进行信号与槽的绑定。

①在UI界面处布置控件并且命名

②对项目进行整体重构,让编译器识别到新建的控件对象

③使用QObject内部的静态函数connect实现信号量与槽的关联

connect函数原型:

static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal,const QObject *receiver, const QMetaMethod &method,Qt::ConnectionType type = Qt::AutoConnection);

参数列表介绍:

sender参数

类型为const QObject*,它是信号的发送者对象的指针。这个对象通常是继承自QObject类的。例如,在一个简单的图形用户界面应用中,QPushButton按钮对象就可以作为信号发送者。当按钮被点击时,它会发送clicked信号。

signal参数

类型为const QMetaMethod&,它代表发送者对象的信号。信号是在QObject的子类中使用signals关键字声明的成员函数。信号没有函数体,它的作用是在特定事件发生时(如按钮点击、定时器超时等)发出通知。例如,QPushButton类中的clicked(bool)信号,当按钮被点击时会发出这个信号,并且可以携带一个布尔值(表示按钮是否被选中状态等相关信息)。

receiver参数

类型为const QObject*,它是信号接收者对象的指针。接收者也是QObject或其派生类的对象。比如,可能是一个自定义的窗口类对象,用于处理按钮点击后的操作。

method参数

类型为const QMetaMethod&,它代表接收者对象中的槽函数。槽函数是普通的成员函数,使用slots关键字(在旧版本的 Qt 中使用,现在也可以是普通成员函数)或者是普通的publicprivate等访问权限的成员函数来定义。当信号被发射时,对应的槽函数会被调用。例如,在接收者类中有一个onButtonClicked()函数,它可以作为槽函数来处理按钮点击信号。

type参数

类型为Qt::ConnectionType,默认值是Qt::AutoConnection。这个参数用于指定信号和槽的连接类型。主要有以下几种连接类型:

  • Qt::AutoConnection
    • 这是默认的连接类型。如果信号发射和接收者在同一个线程中,那么会使用Qt::DirectConnection方式连接;如果信号发射和接收者在不同的线程中,会使用Qt::QueuedConnection方式连接。这种自动选择的方式使得信号 - 槽机制在多线程和单线程环境下都能比较方便地工作。
  • Qt::DirectConnection
    • 当信号被发射时,槽函数会立即被调用,就好像直接调用普通函数一样。这种连接方式在信号发射者和接收者在同一线程中使用时比较合适。但是如果在多线程环境下这样连接,并且槽函数执行时间较长,可能会导致信号发射线程阻塞。
  • Qt::QueuedConnection
    • 当信号被发射时,槽函数的调用会被放到接收者对象所在线程的事件队列中。这意味着槽函数会在接收者线程的事件循环处理到这个队列项时才会被调用。这种方式在多线程环境下可以确保接收者线程的事件循环正常工作,不会被信号发射线程随意干扰。
  • Qt::BlockingQueuedConnection
    • 这种连接方式和Qt::QueuedConnection类似,但是信号发射线程会阻塞,直到槽函数执行完毕。不过要注意,不能在同一线程中使用这种连接方式,否则会导致死锁。
  • Qt::UniqueConnection
    • 这种连接方式可以确保相同的信号和槽之间只有一个连接。如果已经存在这样的连接,再次尝试建立连接时会被忽略。

实际使用:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QObject::connect(ui->btnCon,SIGNAL(clicked()),this,SLOT(on_btnui_clickedMyself()));
}

其中ui->btn是我们在UI界面新建的控件,SIGNAL宏内包含了clicked代表按下控件时发出消息,on_btnui_clickedMyself()函数需要我们进行外部实现。

出于代码规范考虑优先在Widget.h2文件内部定义;

右键选择Refactor进行重构,位置在Widget.cpp文件中

在Widget.cpp文件中重构代码如下:

void Widget::on_btnui_clickedMyself()
{std::cout<<"ObjCon clicked"<<std::endl;
}

测试结果:

自动连接

①拖动控件并且完成命名

②右击选中控件->转到槽

③转到widget.cpp里面进行编辑,撰写槽的函数体,

简单编写一个标准输出语句进行功能测试:

使用Lamdba表达式

①添加了一枚Lambda按键,点击ctrl+b对项目进行整体构建。

②其实本质上依然是使用静态函数connect,只不过因为Lambda表达式是一种匿名函数,所以我们无需再次显式声明slot槽函数。

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//使用connect静态函数QObject::connect(ui->btnCon,SIGNAL(clicked()),this,SLOT(on_btnui_clickedMyself()));//使用Lambda表达式QObject::connect(ui->btnLambda,&QPushButton::clicked,[=](){std::cout<<"Lambda clicked"<<std::endl;});
}

使用函数指针

步骤大同小异

①在可视化界面拖动控件并且命名,顺手按下ctrl+b重构项目

②补充全部代码

Widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <iostream>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//使用connect静态函数QObject::connect(ui->btnCon,SIGNAL(clicked()),this,SLOT(on_btnui_clickedMyself()));//使用Lambda表达式QObject::connect(ui->btnLambda,&QPushButton::clicked,[=](){std::cout<<"Lambda clicked"<<std::endl;});//使用函数指针QObject::connect(ui->btnPointer,&QPushButton::clicked,this,&Widget::on_Pointer_clicked);
}Widget::~Widget()
{delete ui;
}//使用UiDesigner
void Widget::on_btnui_clicked()
{std::cout<<"UiDesigner clicked"<<std::endl;
}void Widget::on_btnui_clickedMyself()
{std::cout<<"ObjCon clicked"<<std::endl;
}void Widget::on_Pointer_clicked()
{std::cout<<"Pointer clicked"<<std::endl;
}

Widget.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_btnui_clicked();void on_btnui_clickedMyself();void on_Pointer_clicked();
private:Ui::Widget *ui;
};
#endif // WIDGET_H

第44讲 自定义信号与槽

介绍

Qt 中,自定义信号与槽是实现对象间通信的一种机制。信号和槽是 Qt 对象通信的核心特性,使得一个对象能够在发生某种事件时通知其他对象。

步骤

自定义信号与槽的实现步骤如下:
定义信号 :在 Qt 中,信号是由 signals 关键字声明的类成员函数。它们不需要实现,只需声明。例如:
class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();signals:void mySignal();void mySignalParams(int value);private:Ui::Widget *ui;
};

定义槽:槽可以是任何普通的成员函数,但通常在类定义中用 slots 关键字标识。槽可以有返回类型,也可以接受参数,但它们的参数类型需要与发出信号的参数类型匹配。例如:

class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();signals:void mySignal();void mySignalParams(int value);private slots:void mySlot();void mySlotParams(int value);private:Ui::Widget *ui;
};

③连接信号与槽

使用静态成员函数 QObject::connect 函数将信号与槽连接起来。当信号被发射时,连接到这个信号的槽将被调用。示例如下:

Widget::Widget(QWidget *parent): QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);connect(this,SIGNAL(mySignal()),this,SLOT(mySlot()));connect(this,SIGNAL(mySignalParams(int y)),this,SLOT(mySlotParams(int x)));
}

注意:SIGNAL(mySignal())以及SLOT(mySlot())是QT环境中的特有语法,SIGNAL()是一个宏,作用是将括号内包含的函数声明为信号,SLOT()也是同理。

语法形式:SIGNAL()宏接受一个函数签名作为参数,这里的函数签名就是mySignal(),它表示定义了一个名为mySignal且无参数的信号。在实际使用中,这个函数并不需要在类中实现具体的函数体内容(因为它只是一个信号声明,其实现由 Qt 的元对象系统在背后处理)。

原理:当在connect语句中使用SIGNAL(mySignal())时,Qt 的元对象编译器(MOC)会在编译阶段对其进行处理。MOC 会分析代码中的信号和槽的声明及连接关系,生成相应的代码来实现信号的发射和槽的调用机制。当对象的状态发生变化等情况需要发出信号时(如在代码中通过emit mySignal();来发射信号),Qt 的元对象系统就会根据之前connect建立的连接关系,找到并调用与之关联的槽函数。

④发射信号

使用emit关键字,语法:emit 函数名称 ();

Widget::Widget(QWidget *parent): QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);connect(this,SIGNAL(mySignal()),this,SLOT(mySlot()));connect(this,SIGNAL(mySignalParams(int y)),this,SLOT(mySlotParams(int x)));emit mySignal();emit mySlotParams(100);
}

知识补充

QDebug Qt 框架中用于输出调试信息的一个类。它提供了一种方便的方式来输出文本到标准输出(通常是控制台),这对于调试 Qt 应用程序非常有用。 QDebug 类可以与 Qt 的信号和槽机制一起使用,使得在响应各种事件时能够输出有用的调试信息。
注意,使用QDebug的前提是包含头文件:
#include <QDebug>
使用 QDebug 的一个典型方式是通过 qDebug() 函数,它返回一个 QDebug 对象。然后,可以使用流操作符 << 来输出各种数据类型。例如:
void Widget::mySlotParams(int value)
{qDebug()<<"SlotParams:"<<value;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习经典模型之ZFNet

1 ZFNet 1.1 模型介绍 ​ ZFNet是由 M a t t h e w Matthew Matthew D . Z e i l e r D. Zeiler D.Zeiler和 R o b Rob Rob F e r g u s Fergus Fergus在AlexNet基础上提出的大型卷积网络&#xff0c;在2013年ILSVRC图像分类竞赛中以11.19%的错误率获得冠军&#xff08;实际…

移动应用开发:简易登录页

文章目录 简介一&#xff0c;创建新活动二&#xff0c;设计UI布局三&#xff0c;编写活动代码四&#xff0c;运行应用程序注意 简介 使用Android Studio编写的简单Android 登录应用程序&#xff0c;该应用程序包含一个登录界面&#xff0c;具有账号和密码两个文本框&#xff0…

网络基础:http协议和内外网划分

声明 学习视频来自B站UP主泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 泷羽sec的个人空间-泷羽sec个人主页-哔哩哔哩视频https://space.bilibili.com/350329294 一&#xff0c;H…

英飞凌Aurix2G TC3XX GPT12模块详解

英飞凌Aurix2G TC3XX GPT12模块详解 本文主要介绍英飞凌 Aurix2G TC3XX系列芯片GPT12模块硬件原理、MCAL相关配置和部分代码实现。 文章目录 英飞凌Aurix2G TC3XX GPT12模块详解1 模块介绍2 功能介绍2.1 结构2.2 独立运行模式2.2.1 定时器模式2.2.2 门控定时器模式2.2.3 计数…

大数据程序猿不可不看的资料大全

​ 随着大数据技术的发展&#xff0c;大数据程序猿在数据采集、处理、分析、存储等方面的技能需求不断增加。要在这个领域保持竞争力&#xff0c;系统性地学习和掌握大数据工具、技术架构和行业趋势是非常重要的。以下为您提供一份围绕大数据程序猿不可不看的资料大全&#xf…

抓包工具WireShark使用记录

目录 网卡选择&#xff1a; 抓包流程&#xff1a; 捕获过滤器 常用捕获过滤器&#xff1a; 抓包数据的显示 显示过滤器&#xff1a; 常用的显示过滤器&#xff1a; 实际工作中&#xff0c;在平台对接&#xff0c;设备对接等常常需要调试接口&#xff0c;PostMan虽然可以进…

MySQL数据迁移到SQLServer数据库

随着云计算技术的发展以及大数据时代的到来&#xff0c;越来越多的企业开始寻求更加高效、安全的数据管理解决方案。MySQL作为一种开源的关系型数据库管理系统&#xff0c;在互联网应用开发中占据了极其重要的位置&#xff1b;而另一方面&#xff0c;Microsoft SQL Server凭借其…

【STM32开发】-FreeRTOS开发入手学习

一、什么是FreeRTOS&#xff1f; FreeRTOS 是 RTOS 系统的一种&#xff0c;FreeRTOS 十分的小巧&#xff0c;可以在资源有限的微控制器中运行&#xff1b; 1、 FreeRTOS是免费的。 2、许多其他半导体厂商产品的 SDK 包就使用 FreeRTOS 作为其操作系统&#xff0c;尤其是 WIFI、…

【软考】系统分析师第二版 新增章节 第20章微服务系统分析与设计

微服务系统是一类基于微服务架构风格的分布式系统&#xff0c;它将应用程序拆分成多个独立的小型服务&#xff0c;每个服务都运行在独立的进程中&#xff0c;并采用轻量级通信协议进行通信。这些服务可以由不同的团队开发、不同的编程语言编写&#xff0c;并且可以按需部署。微…

【笔记】自动驾驶预测与决策规划_Part6_不确定性感知的决策过程

文章目录 0. 前言1. 部分观测的马尔可夫决策过程1.1 POMDP的思想以及与MDP的联系1.1.1 MDP的过程回顾1.1.2 POMDP定义1.1.3 与MDP的联系及区别POMDP 视角MDP 视角决策次数对最优解的影响 1.2 POMDP的3种常规解法1.2.1 连续状态的“Belief MDP”方法1. 信念状态的定义2. Belief …

【SpringBoot】 黑马大事件笔记-day2

目录 用户部分 实体类属性的参数校验 更新用户密码 文章部分 规定josn日期输出格式 分组校验 上期回顾&#xff1a;【SpringBoot】 黑马大事件笔记-day1 用户部分 实体类属性的参数校验 对应的接口文档&#xff1a; 基本信息 请求路径&#xff1a;/user/update 请求方式&#…

HarmonyOS入门 : 获取网络数据,并渲染到界面上

1. 环境搭建 开发HarmonyOS需要安装DevEco Studio&#xff0c;下载地址 : https://developer.huawei.com/consumer/cn/deveco-studio/ 2. 如何入门 入门HarmonyOS我们可以从一个实际的小例子入手&#xff0c;比如获取网络数据&#xff0c;并将其渲染到界面上。 本文就是基于…

AndroidStudio-视图基础

一、设置视图的宽高 1.在XML文件中设置视图宽高 视图宽度通过属性android:layout_width表达&#xff0c;视图高度通过属性android:layout_height表达&#xff0c;宽高的取值主要有下列三种: &#xff08;1&#xff09;wrap_content:表示与内容自适应。对于文本视图来说&…

三菱QD77MS定位模块紧急停止功能

“紧急停止功能” 是通过简单运动模块的外部输入连接用连接器上连接的紧急停止输入&#xff0c;对同服放大器的全部轴进行批量停止的功能。(初始值为“0:有效”。)通过“[r.82]紧急停止有效/无效设置”可以选择紧急停止输入的有效/无效。 [1]控制内容 将“[r82]紧急停止有效/无…

Android JNI 技术入门指南

引言 在Android开发中&#xff0c;Java是一种主要的编程语言&#xff0c;然而&#xff0c;对于一些性能要求较高的场景&#xff08;如音视频处理、图像处理、计算密集型任务等&#xff09;&#xff0c;我们可能需要使用到C或C等语言来编写底层的高效代码。为了实现Java代码与C…

Js — 定时器

有两种&#xff1a;setInterval 和 setTimeout 间隔时间单位为毫秒 setInterval 每隔指定的毫秒数重复执行一个函数或代码 开启定时器&#xff1a;setInterval(函数&#xff0c;间隔时间) 作用&#xff1a;每隔一段时间调用这个函数 注意&#xff1a;它不是立即执行&#x…

H5播放器EasyPlayer.js 流媒体播放器是否支持npm(yarn) install 安装?

EasyPlayer.js H5播放器是一款功能强大的H5视频播放器&#xff0c;它支持多种流媒体协议播放&#xff0c;包括WebSocket-FLV、HTTP-FLV、HLS&#xff08;m3u8&#xff09;、WebRTC等格式的视频流。它不仅支持H.264和H.265编码格式&#xff0c;还具备实时录像、低延时直播等功能…

前端刺客系列----Vue 3 入门介绍

目录 一.什么是 Vue 3&#xff1f; 二.Vue 3 的主要特性 三,Vue3项目实战 四.总结 在前端开发的世界里&#xff0c;Vue.js 作为一款渐进式的 JavaScript 框架&#xff0c;已成为许多开发者的首选工具。自从 Vue 3 发布以来&#xff0c;它带来了许多重要的改进和新特性&…

【论文复现】MSA+抑郁症模型总结(三)

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀MSA抑郁症模型 热门研究领域&#xff1a;情感计算的横向发展1. 概述2. 论文地址3. 研究背景4. 主要贡献5. 模型结构和代码6. 数据集介绍7. 性…

Linux 实验:日志的备份与恢复 xfs文件系统

添加一个新的硬盘&#xff0c;创建硬盘分区sdc1 设置文件系统格式xfs&#xff0c;提示安装xfsprogs&#xff0c;如果安装失败&#xff0c;在后缀加上--fix-missing直到安装完成为止 mkdir创建空目录data&#xff0c;将sdc1挂载到data&#xff0c;data是根目录下新建的目录&…