C++ Qt 学习(一):Qt 入门
- Qt6 安装教程
0. 基础知识
0.1 qmake 和 cmake 对比
- qmake:qt 独有的代码构建工具
- cmake:C++ 通用的代码构建工具,绝大部分 C++ 开源项目都使用 cmake 管理代码
- qt 项目,没有特殊要求,使用 qmake 即可
0.2 Qt 3 个窗口类的区别
- QMainWindow
- 包含菜单栏、工具栏、状态栏
- QMainWindow 使用的场景不多
- QWidget
- 一个普通的窗口,不包含菜单栏、状态栏,除了登录界面
- 新建项目时建议使用 Qwidget,因为大部分的窗口可能都要做成无边框窗口,需要自定义标题栏,实现拉伸等
- QDialog
- 对话框,常用来做登录窗口、弹出窗口 (例如设置界面)
1. 图片查看软件
1.1 main.cpp
#include "widget.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec();
}
1.2 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:void open1(); // 基础版本void open2(); // 记住上次打开的路径,并指定默认的路径为 文档/图片void open3(); // 图片自适应显示private slots:void on_btnOpen_clicked();private:Ui::Widget *ui;
};
#endif // WIDGET_H
1.3 widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QSettings> // 用于读取和写入应用程序的设置和配置信息
#include <QDebug>
#include <QStandardPaths>
#include <memory> // 智能指针Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->label_image->clear();
}Widget::~Widget() {delete ui;
}void Widget::open1() {// QFileDialog::getOpenFileName() 用于显示一个打开文件对话框,并返回用户选择的文件路径// 参数:指向当前窗口的指针 this,打开的窗口标题,默认打开路径,文件类型过滤器QString filename = QFileDialog::getOpenFileName(this, "请选择图片", "D:/", "图片(*.png *jpg);");if(filename.isEmpty()) {return;}ui->lineEdit_path->setText(filename); // 显示图片路径ui->label_image->setPixmap((QPixmap(filename))); // 显示图片
}// 记住上次打开的路径,并指定默认的路径为 文档/图片
void Widget::open2() {// qApp->applicationDirPath() 用于获取当前应用程序所在的目录路径// "/config/Setting.ini" 是一个固定的字符串表示配置文件的路径QString config_path = qApp->applicationDirPath() + "/config/Setting.ini";qDebug() << config_path;// 使用智能指针创建了一个 QSettings 对象,并使用指定的配置文件路径和格式进行初始化// QSettings::IniFormat 是一个枚举值,用于指定配置文件的格式,此处采用的是 ini 格式的配置文件// 通过 pIniSet 指针调用 value() 函数来获取指定键的值,并将其转换为 QString 类型std::unique_ptr<QSettings> pIniSet(new QSettings(config_path, QSettings::IniFormat));QString lastPath = pIniSet->value("/LastPath/path").toString();// 设置默认读取路径为 windows 下 图片 目录if(lastPath.isEmpty()) {lastPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);}QString filename = QFileDialog::getOpenFileName(this, "请选择图片", lastPath, "图片(*.png *jpg);");if(filename.isEmpty()) {return;}ui->lineEdit_path->setText(filename);ui->label_image->setPixmap((QPixmap(filename)));// 找到给定文件名(filename)中最后一个斜杠"/"的位置int end = filename.lastIndexOf("/");// 提取文件名中最后一个斜杠"/"之前的部分,即路径部分QString _path = filename.left(end);// 将键 "/LastPath/path" 的值设置为 _pathpIniSet->setValue("/LastPath/path", _path);qDebug() << _path;
}// 图片自适应显示
void Widget::open3() {QString config_path = qApp->applicationDirPath() + "/config/Setting.ini";qDebug() << config_path;std::unique_ptr<QSettings> pIniSet(new QSettings(config_path, QSettings::IniFormat));QString lastPath = pIniSet->value("/LastPath/path").toString();if(lastPath.isEmpty()) {lastPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);}QString filename = QFileDialog::getOpenFileName(this, "请选择图片", lastPath, "图片(*.png *jpg);");if(filename.isEmpty()) {return;}ui->lineEdit_path->setText(filename);// 图片自适应显示std::unique_ptr<QPixmap> pix(new QPixmap(filename)); // 通过给定的文件名(filename)加载图像数据// 将加载的图像按照 ui->label_image 控件的大小进行缩放// Qt::KeepAspectRatio:保持图像的纵横比例不变pix->scaled(ui->label_image->size(), Qt::KeepAspectRatio);ui->label_image->setScaledContents(true); // 当图像大于控件大小时,将自动缩放以适应控件的大小ui->label_image->setPixmap(*pix); // 设置 ui->label_image 控件的图像为加载并缩放后的图像int end = filename.lastIndexOf("/");QString _path = filename.left(end);pIniSet->setValue("/LastPath/path", _path);qDebug() << _path;
}void Widget::on_btnOpen_clicked() {//open1();//open2();open3();
}
1.4 widget.ui
2. C++ lambda 函数详解
- C++ lambda 表达式的本质就是重载了 operator(),lambda 是一个类,在调用时会进行编译展开,因此 lambda 表达式对象其实就是一个匿名的 functor,所以 lambda 表达式也叫匿名函数对象
- Qt 槽函数可以使用 lambda 函数来写
- C++ 中 lambda 表达式的构成
[捕获列表](形参列表) mutable 异常列表->返回类型 {函数体 }
- 捕获列表:捕获外部变量,捕获的变量可以在函数体中使用,可以省略,即不捕获外部变量
- 形参列表:和普通函数的形参列表一样。可省略,即无参数列表
- mutable:如果有,则表示在函数体中可以修改捕获变量,根据具体需求决定是否需要省略
- 异常列表:noexcept /throw(…),和普通函数的异常列表一样,可省略,即代表可能抛出任何类型的异常
- 返回类型:和函数的返回类型一样。可省略,如省略,编译器将自动推导返回类型
- 函数体:代码实现,可省略,但是没意义
- 捕获方式
- 值捕获:不能在 lambda 表达式中修改捕获变量的值
- 引用捕获:使用引用捕获一个外部变量,需在捕获列表变量前面加上一个引用说明符 &
- 隐式捕获
#include <iostream>using namespace std;int main() {// 1、值捕获int value = 100;auto f = [value](int a, int b)->int {//value++; // 不能在 lambda 表达式中修改捕获变量的值return a + b + value;};cout << f(1, 2) << endl;// 2、引用捕获auto f2 = [&value](int a, int b)->int {value++;return a + b;};cout << f2(1, 3) << endl;cout << "value = " << value << endl;// 3、隐式捕获// = 值捕获// & 引用捕获int age = 123;auto f3 = [&](int a, int b)->int {value++;age++;return a + b;};return 0; }
3. 槽函数的常见写法
-
Qt 4 写法
connect(ui->btnOpen, SIGNAL(clicked), this, SLOT(open()));
- 不推荐这种写法,如果 SIGNAL写错了,或者信号名字、槽函数名字写错了编译器检查不出来,导致程序无响应,引起不必要的误解
-
Qt 5 写法
connect(ui.btnOpen, QPushButton::clicked, this, &Widget::open);
- 推荐使用这种写法
-
lambda 函数表达式写法
connect(ui.btnOpen, &QPushButton::clicked, [=](){// 具体代码实现 });
- 适用于 slot 代码比较少的逻辑
-
直接法
void on_控件名_信号名();
- 这种不用 connect,Qt 自动连接
4. 自定义信号及参数注册
4.1 跨 UI 发送自定义信号
-
如何自定义信号
- 使用signals声明
- 返回值是void
- 在需要发送的地方使用下述方法进行发送
- emit 信号名字(参数);
- 在需要链接的地方使用connect进行链
-
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_btnOpen_clicked();private:Ui::Widget *ui; }; #endif // WIDGET_H
-
dialog.h
- 跨 UI 发送:New File --> Qt Designer Form Class --> Dialog without Buttons
#ifndef DIALOG_H #define DIALOG_H#include <QDialog>namespace Ui { class Dialog; }class Dialog : public QDialog {Q_OBJECTpublic:explicit Dialog(QWidget *parent = nullptr);~Dialog();private slots:void on_btnAdd_clicked();signals:void sig_addOne(int value);private:Ui::Dialog *ui; };#endif // DIALOG_H
-
widget.cpp
#include "widget.h" #include "ui_widget.h" #include "dialog.h" // 跨 UI 头文件Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }void Widget::on_btnOpen_clicked() {Dialog dlg;// 使用 lambda 函数编写槽函数connect(&dlg, &Dialog::sig_addOne, [=](int value) {ui->lineEdit->setText(QString::number(value));});dlg.exec(); // 需放在 connect 后,因为此行为事件循环会阻塞 UI }
-
dialog.cpp
#include "dialog.h" #include "ui_dialog.h"Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) {ui->setupUi(this); }Dialog::~Dialog() {delete ui; }void Dialog::on_btnAdd_clicked() {static int value = 100;emit sig_addOne(value++); // 实现跨 UI 自加操作 }
4.2 跨线程发送自定义信号
Qt 的子线程无法直接修改 ui,需要发送信号到 ui 线程进行修改
-
widget.h
#ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include "childthread.h"QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_btnUpdate_clicked();void showInfo(Score s);private:Ui::Widget *ui; }; #endif // WIDGET_H
-
widget.cpp
#include "widget.h" #include "ui_widget.h" #include <QDebug>Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);qDebug() << "ui thread id = " << QThread::currentThreadId(); }Widget::~Widget() {delete ui; }void Widget::on_btnUpdate_clicked() {ChildThread *ch = new ChildThread();// 以下实现还是在子线程中(不在 ui 线程中),无法直接修改 ui // connect(ch, &ChildThread::sig_SendToUI, [=](Score s) { // string info = s.name + "id = " + to_string(s.id) + " age = " + to_string(s.age); // ui->lineEdit->setText(QString::fromStdString(info)); // // 用于验证 slot 与 ui 下是否同属一个线程(id) // // 结果表明此处的 slot 与子线程的 run() 同属一个线程(id) // qDebug() << "slot thread id = " << QThread::currentThreadId(); // });// 以下实现在 ui 线程 (主线程) 中,可以直接修改 uiconnect(ch, &ChildThread::sig_SendToUI, this, &Widget::showInfo);ch->start(); }void Widget::showInfo(Score s) {qDebug() << "ui thread id2 = " << QThread::currentThreadId();string info = s.name + "id = " + to_string(s.id) + " age = " + to_string(s.age);ui->lineEdit->setText(QString::fromStdString(info)); }
-
childthread.h
#ifndef CHILDTHREAD_H #define CHILDTHREAD_H#include <QThread> #include <string>using namespace std;struct Score {string name;int id;int age; };class ChildThread : public QThread {Q_OBJECTpublic:ChildThread();protected:void run() override;signals:void sig_SendToUI(Score score); };#endif // CHILDTHREAD_H
-
childthread.cpp
#include "childthread.h" #include <QDebug>ChildThread::ChildThread() {// 非基础类型参数需要注册qRegisterMetaType<Score>("Score");qRegisterMetaType<string>("string"); }void ChildThread::run() {qDebug() << "run thread id = " << QThread::currentThreadId();Score s;s.name = "jack";s.id = 1001;s.age = 26;emit sig_SendToUI(s); // 发送信号 }
4.3 处理信号重名问题
-
例如 QComboBox 的信号
Q_SIGNALS:void currentIndexChanged(int index);void currentIndexChanged(const QString &);
-
解决方案
// 错误写法 connect(ui->comboBox, &QComboBox::currentIndexChanged, this, &Widget::onIndex);// 解决方案一 connect(ui->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onIndex(int)));// 解决方案二 connect(ui->comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &Widget::onIndex);
5. connect 函数详解
template <typename Func1, typename Func2>
static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender,Func1 signal,const typename QtPrivate::FunctionPointer<Func2>::Object *receiver,Func2 slot,Qt::ConnectionType type = Qt::AutoConnection)
enum ConnectionType {AutoConnection,DirectConnection,QueuedConnection,BlockingQueuedConnection,UniqueConnection = 0x80,SingleShotConnection = 0x100,
};
-
AutoConnection
- 默认连接方式,如果接收方在发出信号的线程中,使用 Qt::DirectConnection
- 否则使用 Qt::QueuedConnection,在发出信号时确定连接类型
- Qt 中默认使用 AutoConnection,所以平时写信号槽时都是 4 个参数
-
DirectConnection
- 当发出信号时,插槽立即被调用,槽在发送信号的线程中执行
-
QueuedConnection
- 当控制返回到接收方线程的事件循环时调用槽,槽在接收方的线程中执行
-
BlockingQueuedConnection
- 与 Qt::QueuedConnection 相同,只是发送信号的线程会阻塞,直到槽返回
- 如果接收方存在于发送信号的线程中,则不能使用此连接,否则应用程序将产生死锁
-
UniqueConnection
- 这是一个可以使用按位 OR 与上述任何一种连接类型组合的标志,当 Qt::UniqueConnection 被设置时,如果连接已经存在,QObject::connect() 将失败 (例如,如果相同的信号已经连接到相同的对象对的插槽)
6. Qt 信号槽与 MOC
- moc 全称是 Meta-Object Compiler,也就是 “元对象编译器”
- Qt 程序在交由标准编译器编译之前,先要使用 moc 分析 C++ 源文件
- 如果发现在一个头文件中包含了宏 Q_OBJECT,则会生成另外一个 C++ 源文件,这个源文件中包含了 Q_OBJECT 宏的实现代码,这个新的文件名是原文件名前面加上 moc_ 构成,这个新的文件同样将进入编译系统,最终被链接到二进制代码中去。因此,这个新的文件不是 “替换” 掉旧的文件,而是与原文件一起参与编译
- 另外,还可看出:moc 的执行是在预处理器之前,因为预处理器执行之后,Q_OBJECT 宏就不存在了
可以这么理解,moc 把 Qt 中一些不是 C++ 的关键字做了解析,让 C++ 编译器认识,例如:slots, signals,emit 等,moc 会把这些重新编译解析
7. Qt 内存管理机制
-
C++ 派生类
- 构造顺序:先执行基类的构造函数,再执行派生类的构造函数
- 析构顺序:先执行派生类的析构函数,再执行基类的析构函数
-
Qt 半内存管理机制
- QObject 及其派生类的对象,如果其 parent 非 0,那么其 parent 析构时会析构该对象
- QWidget 及其派生类的对象,可以设置 Qt::WA_DeleteOnClose 标志位,当 close 时会调用 QWidgetPrivate::close_helper,进而调用 deleteLater 析构该对象
8. 解决 Qt 中文乱码问题
-
粘贴别人的代码时,首先在记事本里复制一遍,再粘贴到 QtCreator
-
使用 u8
- ui.pushButton->setText (u8"你好")
-
不使用 QtCreator开发,直接使用 vs2019
-
其他设置
- QtCreator — 选项 — 文本编辑器 — UTF8 BOM 总是删除
- #pragma execution_character_set(“utf-8”)
相关文章:

C++ Qt 学习(一):Qt 入门
Qt6 安装教程 0. 基础知识 0.1 qmake 和 cmake 对比 qmake:qt 独有的代码构建工具cmake:C 通用的代码构建工具,绝大部分 C 开源项目都使用 cmake 管理代码qt 项目,没有特殊要求,使用 qmake 即可 0.2 Qt 3 个窗口类的…...

高性能消息中间件 - Kafka3.x(三)
文章目录 高性能消息中间件 - Kafka3.x(三)Kafka Broker ⭐Kafka Broker概念Zookeeper(新版本可以不使用zk了)⭐Zookeeper的作用 Kafka的选举1:Broker选举Leader⭐Broker核心参数⭐案例:服役新节点和退役旧…...

【八】Linux成神之路
Linux成神之路 简介:最近梳理了一下自己linux系统的学习历程,感觉整个成长过程就很顺利,并没有走弯路,于是想着可以不可以把自己linux系统学习的路线记录下来,能够在大家成长的路上有一点帮助,就在这样的一…...

功能测试用例,需要详细到什么程度?
📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…...

VScode远程连接错误:进程试图写入不存在的管道
使用VScode连接树莓派时,出现远程连接错误:进程试图写入不存在的管道 解决方案: (1)可以进入config所在文件夹,删除文件 (2)无法解决的化尝试下述方法 输入 Remotting-SSH:Settin…...

Python测试之Pytest详解
概要 当涉及到python的测试框架时,pytest是一个功能强大且广泛应用的第三方库。它提供简洁而灵活的方式来编写和执行测试用例,并具有广泛的应用场景。下面是pytest的介绍和详细使用说明: pytest是一个用于python单元测试的框架,它…...

uni-app微信小程序打开第三方地图
需求 小程序中有个按钮点击以后会调用手机中第三方地图进行导航。参数 位置信息 经度 与纬度。 实现方法 uni.openLocation({latitude: Number(地址纬度),longitude: Number(地址经度),name: 地址名称,address: 地址详情,success: function (res) {console.log(打开系统位置地…...
Android NDK开发详解之NDK 使用入门
Android NDK开发详解之NDK 使用入门 下载 NDK 和工具创建或导入原生项目 原生开发套件 (NDK) 是一套工具,使您能够在 Android 应用中使用 C 和 C 代码,并提供众多平台库,您可使用这些平台库管理原生 activity 和访问实体设备组件,…...
nmap指纹识别要点以及又快又准之方法
nmap指纹识别要点以及又快又准之方法 一. 前言:二. nmap识别实验:一. 实验一:IP配置:空间配置:扫描结果:详细输出二. 实验二:IP配置:空间配置:扫描结果:详细输出三. 实验三:IP配置:空间配置:扫描结果:详细输出四. 实验四:IP...

Rust编程基础之6大数据类型
1.Rust数据类型 在 Rust 中, 每一个值都属于某一个 数据类型(data type), 这告诉 Rust 它被指定为何种数据,以便明确数据处理方式。我们将看到两类数据类型子集:标量(scalar)和复合(compound&a…...

06 MIT线性代数-线性无关,基和维数Independence, basis, and dimension
1. 线性无关 Independence Suppose A is m by n with m<n (more unknowns than equations) Then there are nonzero solutions to Ax0 Reason: there will be free variables! A中具有至少一个自由变量,那么Ax0一定具有非零解。A的列向量可以线性组合得到零向…...

Kubernetes 概述以及Kubernetes 集群架构与组件
目录 Kubernetes概述 K8S 是什么 为什么要用 K8S K8S 的特性 Kubernetes 集群架构与组件 核心组件 Master 组件 Node 组件 编辑 Kubernetes 核心概念 常见的K8S按照部署方式 Kubernetes概述 K8S 是什么 K8S 的全称为 Kubernetes,Kubernetes 是一个可移植、可扩…...

GZ035 5G组网与运维赛题第9套
2023年全国职业院校技能大赛 GZ035 5G组网与运维赛项(高职组) 赛题第9套 一、竞赛须知 1.竞赛内容分布 竞赛模块1--5G公共网络规划部署与开通(35分) 子任务1:5G公共网络部署与调试(15分) 子…...
使用Jasypt3.0.3版本对SpringBoot配置文件加密
时间 2023-11-01 使用Jasypt3.0.3版本对SpringBoot配置文件加密 目录 引入依赖使用密钥生成密文配置yml验证是否自动解密 引入依赖 <!--yml 文件加解密--><dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-b…...
生成一篇博客,详细讲解springboot的单点登录功能,有流程图,有源码demo
SpringBoot是目前非常流行的一个Java开发框架,它以简洁的配置和快速的开发效率著称。在实际应用中,单点登录是一个非常重要的功能,它可以让用户在多个应用系统中使用同一个账号登录,提高用户体验和安全性。本文将详细讲解如何在Sp…...

Hadoop、Hive安装
一、 工具 Linux系统:Centos,版本7.0及以上 JDK:jdk1.8 Hadoop:3.1.3 Hive:3.1.2 虚拟机:VMware mysql:5.7.11 工具下载地址: https://pan.baidu.com/s/1JYtUVf2aYl5–i7xO6LOAQ 提取码: xavd…...
PHP自定义函数--输入起始日期和解算日期返回日期差几天和 上一个周期的起始结束日期
/** 日期差几天* param beginDate:2018-01-26 endDatee:2018-01-26* return int days* */ function dateDiff($beginDate, $endDate) {$diff date_diff(date_create($beginDate), date_create($endDate))->format(%R%a);return (int)$diff; }/** 返回上一周期的起始和结束日…...
.net 7 上传文件踩坑
(Name “file”) 没加上这个传不进文件 /// <summary>/// 上传单个文件/// </summary>/// <param name"formFile"></param>/// <returns></returns>[HttpPost("UploadFiles")][FunctionAttribute(MuType.Btn, "…...

C++基础算法④——排序算法(快速、归并附完整代码)
快速排序 快速排序是对冒泡排序的一种改进。 它的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行快速排序,以达到整个序列有序。 假设我们现在对 …...

高防CDN如何在防护cc上大显神通
高级防御CDN(Content Delivery Network)在对抗CC(HTTP Flood)攻击方面扮演着关键的角色,具备以下重要职能和作用: 流量分散:CC攻击的目标是通过大规模的HTTP请求使服务器过载,从而导…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...