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

Qt信号槽机制与UI设计完全指南:从基础原理到实战应用

目录

  • 前言
  • 一、信号槽
    • 1.1 传参
    • 1.2 Qt信号与槽的对应关系
      • 1.2.1一对多关系
      • 1.2.2 多对一关系
  • 二、Designer
  • 三、Layout 布局
    • 3.1 基础用法
    • 3.2 打破布局
    • 3.3 贴合窗口
    • 3.4 伸展器(Spacer)
    • 3.5 嵌套布局
  • 四、ui指针
  • 五、QWidget
  • 六、QLabel 标签使用指南
  • 总结


前言

本篇文章,我们将继续探讨Qt的学习,解锁现代应用开发的无限可能。上一篇文章,我们已经对信号槽进行了初步的探讨,本篇文章我们将会书接上文,继续来探讨信号槽的使用。


一、信号槽

首先补充上篇文章的两个小知识点

需要注意的是,调用connect函数之前,发射者与接收者对象必须均创建完成。

把connect的函数名称改为disconnect,参数不变可以断开信号槽连接。另外,发射者或接收者对象销毁后之前连接的信号槽也会自动断开。

disconnect(sender, SIGNAL(...), receiver, SLOT(...));

1.1 传参

为了理解传参,我们先来做一个例子
【例子】 点击按钮,按钮显示点击的次数。

●text : QString
按钮显示的文字

// int → QString
QString QString::number(int n)            [static]
dialog.h#ifndef DIALOG_H
#define DIALOG_H// 包含必要的头文件
#include <QDialog>       // Qt对话框基类
#include <QPushButton>   // Qt按钮控件// 自定义对话框类,继承自QDialog
class Dialog : public QDialog
{Q_OBJECT  // Qt宏,启用信号槽机制public:// 构造函数// @param parent 父窗口指针,默认为nullptrDialog(QWidget *parent = 0);// 析构函数~Dialog();private:QPushButton* btn;  // 按钮控件指针int count;         // 记录按钮被点击的次数private slots:// 按钮点击的槽函数void btnClickedSlot();
};#endif // DIALOG_H
dialog.cpp// 包含对话框类的头文件
#include "dialog.h"// 对话框类的构造函数
Dialog::Dialog(QWidget *parent): QDialog(parent), count(0) // 使用构造初始化列表初始化父类和计数器count
{// 设置对话框窗口大小为300x300像素resize(300, 300);// 创建一个显示"0"的按钮,并指定父对象为当前对话框btn = new QPushButton("0", this);// 将按钮移动到窗口中央位置// 计算方式:窗口宽度/2 - 按钮宽度/2,窗口高度/2 - 按钮高度/2btn->move(300/2 - btn->width()/2, 300/2 - btn->height()/2);// 连接按钮的clicked信号到本类的btnClickedSlot槽函数connect(btn, SIGNAL(clicked()),this, SLOT(btnClickedSlot()));
}// 按钮点击的槽函数实现
void Dialog::btnClickedSlot()
{// 计数器自增1count++;// 将整型计数器转换为QString类型QString text = QString::number(count);// 更新按钮上显示的文本为当前计数值btn->setText(text);
}// 对话框类的析构函数
Dialog::~Dialog()
{// 释放按钮对象的内存delete btn;
}

下面为了讲解信号槽传参,强行多增加一个信号槽的理解,本质上信号槽传参是为了解决后期不同对象之间的传参问题。

dialog.h#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QPushButton>// 自定义对话框类,继承自QDialog
class Dialog : public QDialog
{Q_OBJECT  // 启用Qt的元对象系统(信号槽机制等)public:Dialog(QWidget *parent = 0);  // 构造函数,parent参数指定父窗口~Dialog();  // 析构函数private:QPushButton* btn;  // 按钮指针int count;  // 记录按钮被点击的次数private slots:// 槽函数声明void btnClickedSlot();  // 处理按钮点击事件的槽函数void countSlot(int);  // 接收int类型参数的槽函数signals:// 信号声明void countSignal(int);  // 自定义信号,携带一个int类型参数
};#endif // DIALOG_H
dialog.cpp// 包含对话框类的头文件
#include "dialog.h"/*** @brief Dialog类的构造函数* @param parent 父窗口指针,默认为nullptr*/
Dialog::Dialog(QWidget *parent): QDialog(parent), count(0) // 使用构造初始化列表初始化父类和计数器count
{// 设置对话框窗口大小为300x300像素resize(300, 300);// 创建一个显示"0"的按钮,并指定父对象为当前对话框btn = new QPushButton("0", this);// 将按钮移动到窗口中央位置// 计算方式:窗口宽度/2 - 按钮宽度/2,窗口高度/2 - 按钮高度/2btn->move(300/2 - btn->width()/2, 300/2 - btn->height()/2);// 连接按钮的clicked信号到btnClickedSlot槽函数// 当按钮被点击时,会触发btnClickedSlot函数connect(btn, SIGNAL(clicked()),this, SLOT(btnClickedSlot()));// 连接自定义信号countSignal到countSlot槽函数// 这是一个自连接,当countSignal信号发射时,会触发countSlot函数connect(this, SIGNAL(countSignal(int)),this, SLOT(countSlot(int)));
}/*** @brief 按钮点击的槽函数* 当按钮被点击时,发射带参数的自定义信号*/
void Dialog::btnClickedSlot()
{// 先递增count,然后发射countSignal信号,携带count值作为参数emit countSignal(++count);
}/*** @brief 处理计数信号的槽函数* @param count 接收到的计数值* 将计数值显示在按钮上*/
void Dialog::countSlot(int count)
{// 将整型count转换为QString类型QString text = QString::number(count);// 设置按钮文本为当前计数值btn->setText(text);
}/*** @brief Dialog类的析构函数* 释放动态分配的按钮对象*/
Dialog::~Dialog()
{// 删除按钮对象,释放内存delete btn;
}

1.2 Qt信号与槽的对应关系

1.2.1一对多关系

概念
同一个信号可以同时连接到多个槽
槽函数也是成员函数,可以直接调用
优化技巧: 可以把多个槽函数放在一个槽函数中调用,将一对多优化为一对一结构

dialog.h#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>          // 包含QDialog头文件,用于创建对话框窗口
#include <QPushButton>      // 包含QPushButton头文件,用于创建按钮控件
#include <QDebug>           // 包含QDebug头文件,用于调试输出// Dialog类继承自QDialog,表示一个对话框窗口
class Dialog : public QDialog
{Q_OBJECT  // 宏定义,启用Qt的元对象系统(信号槽机制等)public:Dialog(QWidget *parent = 0);  // 构造函数,parent参数指定父窗口~Dialog();                    // 析构函数private:QPushButton* btn;   // 私有成员变量:按钮1QPushButton* btn2;  // 私有成员变量:按钮2private slots:void mySlot1();  // 私有槽函数1(用于响应信号)void mySlot2();  // 私有槽函数2void mySlot3();  // 私有槽函数3
};#endif // DIALOG_H
dialog.cpp#include "dialog.h"// 对话框类的构造函数
Dialog::Dialog(QWidget *parent): QDialog(parent)  // 调用父类QDialog的构造函数
{resize(300,300);  // 设置对话框大小为300x300像素// 创建"一对多"按钮并设置位置btn = new QPushButton("一对多",this);btn->move(100,100);// 创建"一对一"按钮并设置位置btn2 = new QPushButton("一对一",this);btn2->move(100,150);// 信号与槽连接:一对多示例// 将btn的clicked()信号同时连接到mySlot1()和mySlot2()两个槽函数connect(btn,SIGNAL(clicked()),this,SLOT(mySlot1()));connect(btn,SIGNAL(clicked()),this,SLOT(mySlot2()));// 信号与槽连接:一对一示例// 将btn2的clicked()信号连接到mySlot3()槽函数connect(btn2,SIGNAL(clicked()),this,SLOT(mySlot3()));
}// 槽函数1:输出"A"
void Dialog::mySlot1()
{qDebug() << "A";
}// 槽函数2:输出"B"
void Dialog::mySlot2()
{qDebug() << "B";
}// 槽函数3:调用mySlot1和mySlot2
void Dialog::mySlot3()
{// 直接调用mySlot1和mySlot2mySlot1();mySlot2();
}// 析构函数:释放按钮对象
Dialog::~Dialog()
{delete btn;   // 释放"一对多"按钮delete btn2;  // 释放"一对一"按钮
}

1.2.2 多对一关系

概念
多个信号可以同时连接到一个槽
可以使用QObject::sender()函数判断当前是哪个发射者触发的槽函数
该函数返回发射者对象的地址(protected成员函数)

// 可以返回发射者对象的地址
QObject * QObject::sender() const        [protected]

示例代码

dialog.h#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>       // 包含QDialog头文件,用于创建对话框窗口
#include <QPushButton>   // 包含QPushButton头文件,用于创建按钮控件
#include <QDebug>        // 包含QDebug头文件,用于调试输出// Dialog类继承自QDialog,表示一个对话框窗口
class Dialog : public QDialog
{Q_OBJECT  // 必须的宏,用于支持Qt的信号和槽机制public:Dialog(QWidget *parent = 0);  // 构造函数,parent参数指定父窗口~Dialog();                    // 析构函数private:QPushButton* btn;   // 私有成员变量:按钮1QPushButton* btn2;  // 私有成员变量:按钮2private slots:void mySlot();      // 私有槽函数,用于处理按钮点击等信号
};#endif // DIALOG_H
dialog.cpp#include "dialog.h"// 对话框类的构造函数
Dialog::Dialog(QWidget *parent): QDialog(parent)  // 调用父类QDialog的构造函数
{resize(300,300);  // 设置对话框窗口大小为300x300像素// 创建第一个按钮,显示文本为"多对一",父对象为当前对话框btn = new QPushButton("多对一",this);btn->move(100,100);  // 将按钮移动到(100,100)位置// 创建第二个按钮,显示文本为"多对一",父对象为当前对话框btn2 = new QPushButton("多对一",this);btn2->move(100,150);  // 将按钮移动到(100,150)位置// 多对一信号槽连接// 将btn的clicked()信号连接到当前对象的mySlot()槽connect(btn,SIGNAL(clicked()),this,SLOT(mySlot()));// 将btn2的clicked()信号连接到当前对象的mySlot()槽connect(btn2,SIGNAL(clicked()),this,SLOT(mySlot()));
}// 自定义槽函数
void Dialog::mySlot()
{// 通过sender()判断是哪个按钮触发的信号if(sender() == btn)  // 如果是btn按钮{qDebug() << "随便输出个什么A";  // 输出调试信息A}else if(sender() == btn2)  // 如果是btn2按钮{qDebug() << "随便输出个什么B";  // 输出调试信息B}
}// 对话框类的析构函数
Dialog::~Dialog()
{delete btn;   // 释放btn按钮的内存delete btn2;  // 释放btn2按钮的内存
}

二、Designer

定义

Qt Designer 是 Qt 框架自带的可视化界面设计工具,用于快速创建 GUI 界面。

核心功能

通过拖拽组件设计界面,自动生成 ui 文件(XML 格式)。
与 Qt Creator 深度集成,双击 .ui 文件即可启动 Designer。

与代码的关系

Designer 的所有操作均可通过 C++ 代码实现,二者功能等价,但C++效率更高。
生成的 ui 文件会被编译为对应的 C++ 头文件(如 ui_xxx.h),供程序调用。
Designer 界面功能分布

组件工具箱:包含按钮、文本框等可拖拽控件。
属性编辑器:调整选中组件的属性(如尺寸、文本)。
信号/槽编辑器:可视化配置组件的事件响应。
布局工具:快速对齐和排列组件。

使用流程示例

  • 在 Qt Creator 中创建项目,添加 .ui 文件。
  • 双击 .ui 文件启动 Designer,拖拽组件设计界面。
  • 保存后,Qt 自动生成 XML 代码,编译时转换为 C++ 代码。
  • 在业务逻辑中通过 ui->组件名 访问界面元素。
    -工作界面

三、Layout 布局

3.1 基础用法

定义: 布局是一个透明的容器,内部组件按预设规则自动排列。
主要类型:
垂直布局:组件垂直排列(纵向)。
水平布局:组件水平排列(横向)。
两者除方向外,其他属性基本一致。
基础用法

常用属性:
间距(Spacing)、对齐方式(Alignment)、边距(Padding)等。
在这里插入图片描述


3.2 打破布局

作用: 移除外层布局但保留内部组件。
操作步骤:
选中目标布局。
点击工具栏的 “打破布局” 按钮。
注意: 直接删除布局会连带删除内部组件,需谨慎操作。
在这里插入图片描述


3.3 贴合窗口

作用:使最外层布局自适应窗口大小变化。
操作步骤:
选中窗口(或顶层布局)。
点击工具栏的 “贴合窗口” 按钮。
原理:在窗口内嵌套一个自动伸缩的布局。
取消方式:与打破布局相同(选中后点击“打破布局”)。
在这里插入图片描述


3.4 伸展器(Spacer)

功能: 在布局中填充空白区域,调整组件间距。
在这里插入图片描述
应用场景:
实现组件靠左/右/顶部/底部对齐。
动态分配剩余空间。
在这里插入图片描述


3.5 嵌套布局

用途:通过多层布局嵌套实现复杂界面设计。
关键点:
内层布局整体被视为外层布局的一个子组件。
可混合使用垂直、水平布局及伸展器。
在这里插入图片描述
在这里插入图片描述


四、ui指针

在这里插入图片描述


五、QWidget

QWidget 是 Qt 框架中所有用户界面组件的基类,提供了基础的属性和功能,其派生类(如按钮、窗口、标签等)会继承这些特性。以下是其常用属性和功能的整理:
在这里插入图片描述


六、QLabel 标签使用指南

基本特性
用途:仅用于文字和图片信息展示,不可交互操作。
图片资源管理规范
开发步骤:

准备图片

选择分辨率/大小适中的图片
命名要求:纯英文,不含中文字符
存放位置:项目工作目录

创建资源文件

右键项目 → “Add New File”
选择文件类型 → 命名资源文件 → 完成创建

管理资源文件

右键资源文件 → “Open in Editor”
首次使用需设置虚拟路径前缀
添加图片到资源文件中

使用资源

Designer中需先点击资源按钮
支持C++代码和Designer两种使用方式

代码操作图片
核心函数:

静态图片处理

// 构造函数(虚拟路径参数)
QPixmap::QPixmap(const QString &fileName)
// 图片缩放
// width: 目标宽度 | height: 目标高度
// aspectRatioMode: 缩放模式(默认忽略比例)
// transformMode: 插值方法(默认快速变换)
QPixmap QPixmap::scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio,Qt::TransformationMode transformMode = Qt::FastTransformation) const

动态图片处理

// 动图构造函数(必须堆内存分配,参数为虚拟路径)
QMovie::QMovie(const QString &fileName)
// 开始播放
void QMovie::start() [slot]

代码示例
QLabel 代码压缩包


总结

本文全面解析了Qt框架中的信号槽机制与UI设计核心知识,首先详细讲解了信号槽的连接与断开、参数传递以及一对多/多对一的对应关系实现,通过计数器案例演示了信号传参的实际应用;接着系统介绍了Qt Designer可视化设计工具的功能布局、使用流程以及与代码的对应关系;然后深入剖析了布局管理的各类技巧,包括基础布局、打破布局、贴合窗口、伸展器使用和嵌套布局等实用方法;最后讲解了ui指针的访问方式和QWidget/QLabel组件的核心功能,特别提供了图片资源管理规范和动静态图片处理的代码示例,为开发者提供了从原理到实践的完整Qt开发指南。

相关文章:

Qt信号槽机制与UI设计完全指南:从基础原理到实战应用

目录 前言一、信号槽1.1 传参1.2 Qt信号与槽的对应关系1.2.1一对多关系1.2.2 多对一关系 二、Designer三、Layout 布局3.1 基础用法3.2 打破布局3.3 贴合窗口3.4 伸展器&#xff08;Spacer&#xff09;3.5 嵌套布局 四、ui指针五、QWidget六、QLabel 标签使用指南总结 前言 本…...

Anaconda环境中conda与pip命令的区别

文章目录 conda与pip的基本区别在Anaconda环境中的实际差异安装包环境管理依赖解决示例最佳实践建议 常见问题解答 conda与pip的基本区别 包来源与生态系统 conda&#xff1a;从Anaconda默认仓库或conda-forge等渠道获取包 不仅管理Python包&#xff0c;还能管理非Python依赖&…...

XBL6501/02/03在POE设备上的应用方案

前言&#xff1a; 在当今数字化时代&#xff0c;POE&#xff08;Power over Ethernet&#xff09;设备因其能够通过以太网线同时传输数据和电力而被广泛应用。为了满足这些设备日益增长的电源需求&#xff0c;芯伯乐推出了XBL6501/02/03系列DC-DC电源芯片&#xff0c;为POE设备…...

编程题 03-树2 List Leaves【PAT】

文章目录 题目输入格式输出格式输入样例输出样例 题解解题思路完整代码 编程练习题目集目录 题目 Given a tree, you are supposed to list all the leaves in the order of top down, and left to right. 输入格式 Each input file contains one test case. For each case, …...

生信小白学Rust-03

语句和表达式 举个栗子&#x1f330; fn add_with_extra(x: i32, y: i32) -> i32 {let x x 1; // 语句let y y 5; // 语句x y // 表达式 } // 语句执行操作 // 表达式会返回一个值 怎么区分呢&#xff0c;目前我的理解是只要返回了值&#xff0c;那它就是表达式 fn…...

缺乏需求优先级划分时,如何合理分配资源?

当需求优先级不明确时&#xff0c;合理分配资源的关键在于建立统一评估标准、实施敏捷资源管理、提升团队协作效率、加强跨部门沟通机制。尤其是建立统一评估标准至关重要&#xff0c;它能帮助组织快速判断各项需求的重要性与紧迫性&#xff0c;从而实现资源的动态匹配与有效利…...

操作系统学习笔记第3章 内存管理(灰灰题库)

1. 单选题 某页式存储管理系统中&#xff0c;主存为 128KB&#xff0c;分成 32 块&#xff0c;块号为 0、1、2、3、…、31。某作业有 5 块&#xff0c;其页号为 0、1、2、3、4&#xff0c;被分别装入主存的 3、8、4、6、9 块中。有一逻辑地址为 [3, 70]&#xff08;其中方括号中…...

详细分析python 中的deque 以及和list 的用法区别

dqque :双端队列&#xff0c;可以快速的从另外一侧追加和推出对象,deque是一个双向链表&#xff0c;针对list连续的数据结构插入和删除进行优化。它提供了两端都可以操作的序列&#xff0c;这表示在序列的前后你都可以执行添加或删除操作。 通过上图可以看出&#xff0c;deque …...

Stack overflow

本文来源 &#xff1a;腾讯元宝 Stack Overflow - Where Developers Learn, Share, & Build Careers 开发者学习&#xff0c;分享 通过学习、工作和经验积累等方式&#xff0c;逐步建立和发展自己的职业生涯。 Find answers to your technical questions and help othe…...

和为target问题汇总

文章目录 习题377.组合总和 IV494.目标和 和为target的问题&#xff0c;可以有很多种问题的形式的考察&#xff0c;当然&#xff0c;及时的总结与回顾有利于我们熟练掌握这些知识&#xff01; 习题 377.组合总和 IV 377.组合总和 IV 思路分析&#xff1a;通过观察&#xff0…...

STM32单片机内存分配详细讲解

单片机的内存无非就两种&#xff0c;内部FLASH和SRAM&#xff0c;最多再加上一个外部的FLASH拓展。在这里我以STM32F103C8T6为例子讲解FLASH和SRAM。 STM32F103C8T6具有64KB的闪存和20KB的SRAM。 一. Flash 1.1 定义 非易失性存储器&#xff0c;即使在断电后&#xff0c;其所…...

RedHat7 如何更换yum镜像源

RedHat7如何更换yum镜像源&#xff1f; # 删除系统自带 yum rpm -qa|grep -e yum -e python-urlgrabber |xargs rpm -e --nodeps# 下载yum与wget的rpm软件包 curl -O http://mirrors.aliyun.com/centos/7/os/x86_64/Packages/yum-3.4.3-168.el7.centos.noarch.rpm curl -O ht…...

Ubuntu 编译SRS和ZLMediaKit用于视频推拉流

SRS实现视频的rtmp webrtc推流 ZLMediaKit编译生成MediaServer实现rtsp推流 SRS指定某个固定网卡&#xff0c;修改程序后重新编译 打开SRS-4.0.0/trunk/src/app/srs_app_rtc_server.cpp&#xff0c;在 232 行后面添加&#xff1a; ZLMediaKit编译后文件存放在ZLMediakit/rele…...

Intellij报错:the file size(3.47M) exceeds configured limit (2.56MB)

今天在部署一个教学平台的时候&#xff0c;当执行数据库脚本出现了以上问题。 自己把解决的方案分享给大家&#xff1a; 于IntelliJ IDEA或PyCharm&#xff0c;可以通过编辑idea.properties文件来增加文件大小限制。 打开idea.properties文件&#xff0c;通常位于IDE的安装目录…...

大数据技术全景解析:Spark、Hadoop、Hive与SQL的协作与实战

引言&#xff1a;当数据成为新时代的“石油” 在数字经济时代&#xff0c;数据量以每年50%的速度爆发式增长。如何高效存储、处理和分析PB级数据&#xff0c;成为企业竞争力的核心命题。本文将通过通俗类比场景化拆解&#xff0c;带你深入理解四大关键技术&#xff1a;Hadoop、…...

软考软件评测师——软件工程之系统维护

一、系统质量属性 可维护性 衡量软件系统适应修改的难易程度&#xff0c;包括修复缺陷、扩展功能或调整规模的效率。计算公式为&#xff1a;系统可用时间占比 1/(1平均修复时间)&#xff0c;其中平均修复时间(MTTR)指排除故障所需的平均耗时。 可靠性 vs 可用性 可靠性&…...

Unity动画与生命周期函数

一、Animator动画组件 Animator组件是Unity中用于管理和控制动画的主要工具&#xff0c;它可以处理复杂的动画状态机和动画片段之间的过 1.动画状态机 Animator组件的核心是动画状态机&#xff0c;它由多个动画状态和状态之间的过渡组成。可以通过Unity的动画窗口来创建和编辑…...

合并两个有序数组的高效算法详解

合并两个有序数组的高效算法详解 **合并两个有序数组的高效算法详解****1. 问题描述****2. 常见解法分析****方法 1&#xff1a;合并后排序&#xff08;暴力法&#xff09;****方法 2&#xff1a;双指针法&#xff08;额外空间&#xff09;** **3. 最优解法&#xff1a;双指针从…...

虚拟Python 环境构建器virtualenv安装(macOS版)

前提 之前我们使用pyenv安装好了Python 3.13.3&#xff0c;并且&#xff0c;全局都使用这个版本的python。现在我们来安装virtualenv。 pipx安装 brew install pipx pipx ensurepath sudo pipx ensurepath --global # optional to allow pipx actions with --global argumen…...

解决ubuntu20中tracker占用过多cpu,引起的风扇狂转

track是linux中的文件索引工具&#xff0c;ubuntu18之前是默认不安装的&#xff0c;所以在升级到20后会默认安装&#xff0c;它是和桌面程序gnome绑定的&#xff0c;甚至还有很多依赖项&#xff0c;导致无法删除&#xff0c;一旦删除很多依赖项都不能运行&#xff0c;禁用也很难…...

在线文档管理系统 spring boot➕vue|源码+数据库+部署教程

&#x1f4cc; 一、项目简介 本系统采用Spring Boot Vue ElementUI技术栈&#xff0c;支持管理员和员工两类角色&#xff0c;涵盖文档上传、分类管理、公告发布、员工资料维护、部门岗位管理等核心功能。 系统目标是打造一个简洁高效的内部文档管理平台&#xff0c;便于员工…...

在UI 原型设计中,交互规则有哪些核心要素?

在UI 原型设计中&#xff0c;交互规则主要有三个核心要素&#xff0c;分别为重要性、原则与实践&#xff0c;具体表现在&#xff1a; 一、交互规则在 UI 原型设计中的重要性 明确交互逻辑&#xff1a;设计阶段制定交互规则&#xff0c;清晰定义界面元素操作响应。 如社交应用…...

CSS图片垂直居中问题解决方案

在 CSS 中&#xff0c;使用 vertical-align: middle 导致图片略微向下偏移的现象&#xff0c;本质上是由于 行内元素的基线对齐规则 和 父容器上下文环境 共同作用的结果。以下是具体原因和解决方案&#xff1a; 原因详解 1. vertical-align: middle 的真实含义 该属性 不会让…...

STC8H系列单片机STC8H_H头文件功能注释

#ifndef __STC8H_H__ // 条件编译:如果未定义__STC8H_H__宏 #define __STC8H_H__ // 则定义该宏,防止头文件被重复包含 / //包含本头文件后,不用另外再包含"REG51.H" // 提示:本头文件已包含基本寄存器定义 sfr P0 = …...

Python类的力量:第五篇:魔法方法与协议——让类拥有Python的“超能力”

文章目录 前言&#xff1a;从“普通对象”到“Python原生公民”的进化之路 一、魔法方法&#xff1a;赋予对象“超能力”的基因1. 构造与析构&#xff1a;对象生命周期的“魔法开关”2. 字符串表示&#xff1a;对象的“自我介绍”3. 运算符重载&#xff1a;让对象支持“数学魔法…...

OpenResty Manager 介绍与部署(Docker部署)

概述 OpenResty-Manager 是一个基于 OpenResty 构建的开源 Web 管理平台。OpenResty 是一个高性能的 Web 平台&#xff0c;集成了 Nginx 和 LuaJIT&#xff0c;支持强大的脚本功能。OpenResty-Manager 由 Safe3 开发&#xff0c;提供了一个用户友好的界面&#xff0c;用于管理…...

深入解析HTTP协议演进:从1.0到3.0的全面对比

HTTP协议作为互联网的基础协议&#xff0c;经历了多个版本的迭代演进。本文将详细解析HTTP 1.0、HTTP 1.1、HTTP/2和HTTP/3的核心特性与区别&#xff0c;帮助开发者深入理解网络协议的发展脉络。 一、HTTP 1.0&#xff1a;互联网的奠基者 核心特点&#xff1a; 短连接模式&am…...

快速搭建一个electron-vite项目

1. 初始化项目 在命令行中运行以下命令 npm create quick-start/electronlatest也可以通过附加命令行选项直接指定项目名称和你想要使用的模版。例如&#xff0c;要构建一个 Electron Vue 项目&#xff0c;运行: # npm 7&#xff0c;需要添加额外的 --&#xff1a; npm cre…...

【Android】Android 实现一个依赖注入的注解

Android 实现一个依赖注入的注解 &#x1f3af; 目标功能 自定义注解 Inject创建一个 Injector 类&#xff0c;用来扫描并注入对象支持 Activity 或其他类中的字段注入 &#x1f9e9; 步骤一&#xff1a;定义注解 import java.lang.annotation.ElementType; import java.lan…...

unity terrain 在生成草,树,石头等地形障碍的时候,无法触发碰撞导致人物穿过模型

1.terrain地形的草&#xff0c;石头之类要选择模型预制体 2.在人物身上挂碰撞器和刚体&#xff0c;或者单挂一个character controller组件也行 3.在预制体上挂碰撞盒就好了&#xff0c;挂载meshcollider会导致碰撞无效...