qt-C++笔记之动画框架(Qt Animation Framework)入门
qt-C++笔记之动画框架(Qt Animation Framework)入门
code review!
在 Linux 平台上,使用 C++ 和 Qt 框架实现动画是一个非常好的选择。Qt 提供了强大的动画框架(Qt Animation Framework),使得动画的实现变得简单高效。下面将介绍 Qt 动画的基本概念与入门使用,并进一步探讨 QTimeLine
、QEasingCurve
的用法,以及 Qt 动画框架中几个重要的类之间的区别。
文章目录
- qt-C++笔记之动画框架(Qt Animation Framework)入门
- 1. Qt 动画框架简介
- 1.1 核心类
- 1.1.1 QPropertyAnimation
- 1.1.2 QSequentialAnimationGroup
- 1.1.3 QParallelAnimationGroup
- 1.1.4 QGraphicsItemAnimation
- 1.1.5 QAnimationDriver
- 1.2 动画作用域
- 1.2.1 UI 部件动画
- 1.2.2 场景动画
- 1.2.3 自定义动画
- 2. 简单动画示例
- 2.1 示例 1:移动一个按钮
- 2.1.1 代码说明
- 3. 组合动画
- 3.1 示例 2:顺序执行多个动画
- 3.2 示例 3:并行执行多个动画
- 4. 自定义动画曲线
- 4.1 常用曲线类型
- 4.2 自定义动画曲线示例
- 5. 在 QGraphicsView 中实现动画
- 6. 总结
- 7. QTimeLine 是什么
- 7.1 核心功能
- 7.2 关键属性和方法
- 7.3 常见动画曲线(CurveShape)
- 7.4 QTimeLine 的信号
- 7.5 简单用法示例
- 7.6 进阶用法:配合 QGraphicsItemAnimation
- 7.7 优缺点与结论
- 8. QTimeLine 和 QEasingCurve 的区别
- 8.1 一、核心区别
- 8.2 二、QTimeLine 详解
- 8.3 三、QEasingCurve 详解
- 8.4 四、两者关系与配合
- 8.5 五、总结对比
- 9. QAbstractAnimation、QVariantAnimation 和 QPropertyAnimation 的区别
- 9.1 一、继承关系
- 9.2 二、核心区别
- 9.3 三、详细分析
- 9.3.1.`QAbstractAnimation` 示例:自定义动画基类
- 9.3.2.`QVariantAnimation` 示例:插值动画
- 9.3.3.`QPropertyAnimation` 示例:操作对象的属性动画
- 9.3.4.区别总结
- 9.4 四、对比总结
1. Qt 动画框架简介
1.1 核心类
1.1.1 QPropertyAnimation
- 用于对对象属性(如位置、大小、透明度等)进行动画处理,直接操作
QObject
的特定属性。
1.1.2 QSequentialAnimationGroup
- 用于按顺序播放多个动画。
1.1.3 QParallelAnimationGroup
- 用于并行播放多个动画。
1.1.4 QGraphicsItemAnimation
- 用于对
QGraphicsItem
(图形场景中的对象)进行动画处理。 - 通常与
QTimeLine
搭配使用。
1.1.5 QAnimationDriver
- 自定义动画的驱动类,用于更底层地控制动画刷新。
1.2 动画作用域
1.2.1 UI 部件动画
- 对 GUI 组件(如按钮、窗口等)进行动画处理(位置、大小、透明度等)。
1.2.2 场景动画
- 对
QGraphicsView
场景中的对象进行动画处理,适合做复杂的 2D 场景交互或游戏等。
1.2.3 自定义动画
- 如果需要更复杂的动画效果,可以自定义动画逻辑或插值方式。
2. 简单动画示例
2.1 示例 1:移动一个按钮
下面的示例展示了如何使用 QPropertyAnimation
将一个按钮从左上角平滑移动到右下角,并添加弹跳效果:
#include <QApplication>
#include <QPushButton>
#include <QPropertyAnimation>
#include <QEasingCurve>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 创建一个按钮QPushButton button("Move Me");button.resize(100, 50);button.show();// 创建一个属性动画QPropertyAnimation *animation = new QPropertyAnimation(&button, "geometry");// 设置动画时长 2 秒animation->setDuration(2000);// 动画的起始位置animation->setStartValue(QRect(0, 0, 100, 50));// 动画的结束位置animation->setEndValue(QRect(300, 300, 100, 50));// 设置动画曲线(弹跳效果)animation->setEasingCurve(QEasingCurve::OutBounce);// 开始动画animation->start();return app.exec();
}
运行
2.1.1 代码说明
-
QPropertyAnimation animation(&button, "geometry")
- 指定了对按钮的
geometry
属性进行动画,geometry
决定了部件的在屏幕上的位置和大小。
- 指定了对按钮的
-
setStartValue
与setEndValue
- 分别设定了动画的初始位置和结束位置。
-
setEasingCurve(QEasingCurve::OutBounce)
- 设置了弹跳缓动曲线,动画结束时会呈现弹跳的效果。
3. 组合动画
有时我们需要在一个动画之后紧接着播放另一个动画,或者同时播放多个动画,这可以使用 QSequentialAnimationGroup
和 QParallelAnimationGroup
来实现。
3.1 示例 2:顺序执行多个动画
#include <QApplication>
#include <QPushButton>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>int main(int argc, char *argv[]) {QApplication app(argc, argv);QPushButton button("Animate Me");button.resize(100, 50);button.show();// 创建两个属性动画QPropertyAnimation *animation1 = new QPropertyAnimation(&button, "geometry");animation1->setDuration(1000);animation1->setStartValue(QRect(0, 0, 100, 50));animation1->setEndValue(QRect(300, 0, 100, 50));QPropertyAnimation *animation2 = new QPropertyAnimation(&button, "geometry");animation2->setDuration(1000);animation2->setStartValue(QRect(300, 0, 100, 50));animation2->setEndValue(QRect(300, 300, 100, 50));// 创建一个顺序动画组QSequentialAnimationGroup group;group.addAnimation(animation1);group.addAnimation(animation2);// 开始动画group.start();return app.exec();
}
运行
3.2 示例 3:并行执行多个动画
#include <QApplication>
#include <QPushButton>
#include <QLabel>
#include <QPropertyAnimation>
#include <QParallelAnimationGroup>int main(int argc, char *argv[]) {QApplication app(argc, argv);QPushButton button("Button");QLabel label("Label");button.resize(100, 50);label.resize(100, 50);button.show();label.show();// 创建属性动画QPropertyAnimation *buttonAnimation = new QPropertyAnimation(&button, "geometry");buttonAnimation->setDuration(2000);buttonAnimation->setStartValue(QRect(0, 0, 100, 50));buttonAnimation->setEndValue(QRect(300, 300, 100, 50));QPropertyAnimation *labelAnimation = new QPropertyAnimation(&label, "geometry");labelAnimation->setDuration(2000);labelAnimation->setStartValue(QRect(0, 300, 100, 50));labelAnimation->setEndValue(QRect(300, 0, 100, 50));// 创建一个并行动画组QParallelAnimationGroup group;group.addAnimation(buttonAnimation);group.addAnimation(labelAnimation);// 开始动画group.start();return app.exec();
}
运行
4. 自定义动画曲线
Qt 提供了多种内置的动画曲线,比如线性、弹跳、缓动等。如果默认曲线无法满足需求,还可以使用 QEasingCurve
自定义动画曲线。
4.1 常用曲线类型
QEasingCurve::Linear
:线性插值QEasingCurve::InQuad
:缓入二次方QEasingCurve::OutBounce
:弹跳效果
4.2 自定义动画曲线示例
QEasingCurve customCurve([](qreal t) -> qreal {// 这里使用简单的二次函数曲线 y = t^2return t * t;
});
animation->setEasingCurve(customCurve);
5. 在 QGraphicsView 中实现动画
如果使用 QGraphicsView
和 QGraphicsItem
,可以通过 QGraphicsItemAnimation
+ QTimeLine
进行更灵活的动画控制。以下示例演示了如何为图形项做一个旋转动画:
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QTimeLine>
#include <QGraphicsItemAnimation>int main(int argc, char *argv[]) {QApplication app(argc, argv);QGraphicsView view;QGraphicsScene scene;view.setScene(&scene);QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);QTimeLine *timer = new QTimeLine(2000);timer->setFrameRange(0, 100);QGraphicsItemAnimation *animation = new QGraphicsItemAnimation;animation->setItem(rect);animation->setTimeLine(timer);for (int i = 0; i <= 100; ++i) {// 让矩形在 2 秒内旋转 360 度animation->setRotationAt(i / 100.0, i * 3.6);}timer->start();view.show();return app.exec();
}
实际运行程序
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QTimeLine>
#include <QGraphicsItemAnimation>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 创建视图和场景QGraphicsView view;view.move(100, 100); // 屏幕左上角 (100, 100)QGraphicsScene scene;view.setScene(&scene);view.setFixedSize(300, 300); // 窗口大小view.setWindowTitle("Animation Demo"); // 窗口标题// 设置场景范围scene.setSceneRect(0, 0, 300, 300);// 添加矩形QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);rect->setPos(100, 100); // 矩形的初始位置// 创建时间线和动画QTimeLine *timer = new QTimeLine(2000);timer->setFrameRange(0, 100);QGraphicsItemAnimation *animation = new QGraphicsItemAnimation;animation->setItem(rect);animation->setTimeLine(timer);for (int i = 0; i <= 100; ++i) {// 让矩形在 2 秒内旋转 360 度animation->setRotationAt(i / 100.0, i * 3.6);}// 启动动画并显示视图timer->start();view.show();return app.exec();
}
运行
6. 总结
Qt 提供了非常强大的动画框架,适用于各种场景,包括简单的 UI 动画、复杂的场景动画,以及自定义动画效果。建议先从 QPropertyAnimation
入门,熟悉后再学习 QSequentialAnimationGroup
与 QParallelAnimationGroup
的组合用法,以及在 QGraphicsView
场景中使用 QGraphicsItemAnimation
。如果需要更现代化、更丰富的动画效果,还可以进一步探索 QML 动画与 C++ 的结合。
7. QTimeLine 是什么
QTimeLine
是 Qt 提供的一个时间驱动类,主要用于控制动画的时间轴。它可以生成一个时间流,用来精确地管理动画的时长、帧数、循环次数以及动画曲线等。
7.1 核心功能
- 控制动画的时间流(定时触发事件或更新插值)
- 配合
QGraphicsItemAnimation
使用 - 自定义动画的加速、减速或循环模式
7.2 关键属性和方法
属性/方法 | 描述 |
---|---|
setDuration(int ms) | 设置动画总时长(毫秒)。 |
setFrameRange(int start, int end) | 设置帧范围。 |
setCurveShape(QTimeLine::CurveShape) | 设置动画曲线(如线性、缓入、缓出等)。 |
start() | 开始动画。 |
stop() | 停止动画。 |
valueForTime(int ms) | 根据当前时间计算动画进度值(通常在 [0.0, 1.0])。 |
setUpdateInterval(int ms) | 设置更新间隔(毫秒)。 |
setLoopCount(int loops) | 设置动画循环次数(0 表示无限循环)。 |
state() | 获取当前动画状态(Running、Paused、Stopped 等)。 |
7.3 常见动画曲线(CurveShape)
曲线类型 | 描述 |
---|---|
LinearCurve | 线性变化,恒定速度 |
EaseInCurve | 缓入曲线,开始时慢,后期加速 |
EaseOutCurve | 缓出曲线,开始时快,后期减速 |
EaseInOutCurve | 缓入缓出曲线,开始结束时都较慢 |
SineCurve | 正弦曲线,平滑的缓入缓出变化 |
CosineCurve | 余弦曲线,与正弦曲线类似 |
7.4 QTimeLine 的信号
信号 | 描述 |
---|---|
frameChanged(int frame) | 当前帧改变时触发 |
valueChanged(qreal value) | 当前进度值改变时触发(范围 [0.0, 1.0]) |
stateChanged(State newState) | 动画状态改变时触发 |
finished() | 动画结束时触发 |
7.5 简单用法示例
以下例子演示用 QTimeLine
在 2 秒内把按钮从 x=0 移到 x=300:
#include <QApplication>
#include <QPushButton>
#include <QTimeLine>int main(int argc, char *argv[]) {QApplication app(argc, argv);QPushButton button("Move Me");button.resize(100, 50);button.show();QTimeLine timeline(2000); // 动画时长 2 秒timeline.setFrameRange(0, 300); // 帧范围timeline.setCurveShape(QTimeLine::EaseInOutCurve);QObject::connect(&timeline, &QTimeLine::frameChanged, [&button](int frame) {button.move(frame, 100);});timeline.start();return app.exec();
}
运行
7.6 进阶用法:配合 QGraphicsItemAnimation
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QTimeLine>
#include <QGraphicsItemAnimation>int main(int argc, char *argv[]) {QApplication app(argc, argv);QGraphicsScene scene;QGraphicsView view(&scene);QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);QTimeLine *timeline = new QTimeLine(2000);timeline->setFrameRange(0, 100);QGraphicsItemAnimation *animation = new QGraphicsItemAnimation;animation->setItem(rect);animation->setTimeLine(timeline);for (int i = 0; i <= 100; ++i) {animation->setRotationAt(i / 100.0, i * 3.6);}view.show();timeline->start();return app.exec();
}
7.7 优缺点与结论
-
优点
- 提供完整的时间管理(时长、帧数、循环等)
- 可与
QGraphicsItemAnimation
配合,实现更精细的动画控制
-
缺点
- 对于现代的 Qt 属性动画或 QML 动画而言,
QTimeLine
可能显得繁琐 - 需要手动管理插值或场景更新
- 对于现代的 Qt 属性动画或 QML 动画而言,
-
结论
QTimeLine
在需要精准控制帧数或需要自定义时间逻辑的场景下依旧实用
8. QTimeLine 和 QEasingCurve 的区别
这两个类在 Qt 动画框架中分别承担不同的职责,可以相互配合使用,但并不互斥。
8.1 一、核心区别
特性 | QTimeLine | QEasingCurve |
---|---|---|
定义 | 时间轴类,用于生成动画的时间流 | 数学曲线类,用于定义动画的缓动插值 |
作用 | 控制动画的进度(时长、帧数、循环) | 改变动画速度/插值模式(线性、弹跳、缓动等) |
输出 | 当前时间或帧信息 | 根据输入进度返回相应缓动后的数值 |
使用场景 | 精准时间/帧控制 | 定义动画的加速、减速、弹跳等视觉效果 |
8.2 二、QTimeLine 详解
- 提供动画的整体时间控制
- 可以设置时长、帧范围、循环次数、曲线形状
- 常用于
QGraphicsItemAnimation
等需要时间驱动的场合
8.3 三、QEasingCurve 详解
- 定义动画的插值方式(线性、缓入缓出、弹跳等)
- 不独立控制时间,而是根据 [0.0, 1.0] 的输入值,返回不同的插值结果
- 通常与
QPropertyAnimation
或QTimeLine
配合使用
8.4 四、两者关系与配合
QTimeLine
生成一个随时间变化的进度值t
,范围在 [0.0, 1.0]QEasingCurve
根据进度值t
计算出缓动后的插值值- 典型用法:
easedValue = curve.valueForProgress(t)
8.5 五、总结对比
- QTimeLine:管理时间进度与帧信息,提供事件驱动
- QEasingCurve:管理插值模式,使动画效果更平滑或更富表现力
它们可以结合使用,也可分别使用在不同的动画需求场景下。
9. QAbstractAnimation、QVariantAnimation 和 QPropertyAnimation 的区别
在 Qt 动画框架中,这三个类具有从抽象到具体的继承关系,主要差异在于能否直接使用以及应用场景是否针对特定属性。
9.1 一、继承关系
QAbstractAnimation└── QVariantAnimation└── QPropertyAnimation
9.2 二、核心区别
特性 | QAbstractAnimation | QVariantAnimation | QPropertyAnimation |
---|---|---|---|
定义 | 动画框架的抽象基类 | 生成数值插值的动画类,继承自 QAbstractAnimation | 继承自 QVariantAnimation,用于动画化 QObject 的属性 |
作用 | 定义动画的基本接口和生命周期 | 在动画过程中生成从起始到结束的插值数值 | 直接将插值结果应用到属性(如 geometry、pos 等) |
是否可直接使用 | 否,需要子类实现 | 是,可直接插值 | 是,可直接操作属性 |
使用场景 | 自定义动画逻辑(需要自己实现插值或刷新) | 需要插值数值并在动画中使用 | 需要直接为对象属性创建动画(UI 控件、图形项等) |
9.3 三、详细分析
9.3.1.QAbstractAnimation
示例:自定义动画基类
QAbstractAnimation
是一个抽象基类,提供了基本的动画框架。通过继承它,我们可以实现自定义的动画。以下是一个简单的示例程序,创建了一个自定义动画类,使一个数字从 0 变化到 100,并在每次更新时打印值。
#include <QCoreApplication>
#include <QAbstractAnimation>
#include <QTimer>
#include <QDebug>class CustomAnimation : public QAbstractAnimation {Q_OBJECTpublic:CustomAnimation(QObject *parent = nullptr) : QAbstractAnimation(parent), m_value(0) {}int duration() const override {return 5000; // 动画持续时间为 5 秒}protected:// 更新动画进度void updateCurrentTime(int currentTime) override {m_value = (100 * currentTime) / duration(); // 根据当前时间计算值qDebug() << "Current value:" << m_value;}private:int m_value; // 当前值
};int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);CustomAnimation animation;animation.start();QTimer::singleShot(6000, &app, &QCoreApplication::quit); // 6秒后退出程序return app.exec();
}#include "main.moc"
运行
特点:
- 用途:
QAbstractAnimation
是所有动画类的基类,可以通过继承它来实现完全自定义的动画逻辑。 - 灵活性:需要手动实现
updateCurrentTime()
和指定动画持续时间。 - 适用场景:当现有的
QVariantAnimation
或QPropertyAnimation
无法满足需求时使用。
9.3.2.QVariantAnimation
示例:插值动画
QVariantAnimation
可以在两种值之间进行插值计算(支持整数、浮点数、颜色等),并在每次值更新时发出信号。以下是一个示例程序,通过插值计算让颜色从红色渐变到蓝色。
#include <QApplication>
#include <QVariantAnimation>
#include <QDebug>int main(int argc, char *argv[]) {QApplication app(argc, argv);QVariantAnimation animation;animation.setDuration(3000); // 动画持续时间为 3 秒animation.setStartValue(QColor(Qt::red)); // 起始值:红色animation.setEndValue(QColor(Qt::blue)); // 结束值:蓝色QObject::connect(&animation, &QVariantAnimation::valueChanged, [](const QVariant &value) {QColor color = value.value<QColor>();qDebug() << "Current color:" << color;});animation.start();QTimer::singleShot(4000, &app, &QCoreApplication::quit); // 4秒后退出程序return app.exec();
}
运行
特点:
- 用途:
QVariantAnimation
是一个通用的插值动画类,支持多种类型(如整数、浮点数、颜色等)的值变化。 - 插值计算:根据动画进度自动计算中间值,并通过
valueChanged()
信号发出。 - 适用场景:需要在两个值之间平滑过渡时使用,例如颜色渐变、大小调整等。
9.3.3.QPropertyAnimation
示例:操作对象的属性动画
QPropertyAnimation
是一个常用的动画类,用于对 QObject 的属性(如位置、大小、颜色等)进行动画处理。以下是一个示例程序,通过动画让一个矩形从左移到右。
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QPropertyAnimation>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 创建场景和矩形QGraphicsScene scene;QGraphicsRectItem *rect = scene.addRect(0, 0, 50, 50, Qt::NoPen, Qt::blue);rect->setPos(0, 0);QGraphicsView view(&scene);view.setFixedSize(400, 200);view.show();// 创建属性动画QPropertyAnimation animation(rect, "pos"); // 动画作用于矩形的 "pos" 属性animation.setDuration(2000); // 动画持续时间为 2 秒animation.setStartValue(QPointF(0, 0)); // 起始位置animation.setEndValue(QPointF(300, 0)); // 结束位置animation.setEasingCurve(QEasingCurve::InOutQuad); // 平滑效果animation.start();return app.exec();
}
运行
特点:
- 用途:
QPropertyAnimation
是专门设计用于操作 QObject 的属性的动画类。 - 自动绑定属性:通过指定属性名称(如
"pos"
、"size"
等),直接修改对象的属性值。 - 适用场景:对象的移动、缩放、透明度变化等动画效果。
9.3.4.区别总结
动画类 | 主要特点 | 适用场景 |
---|---|---|
QAbstractAnimation | 抽象基类,允许完全自定义动画逻辑 | 特殊需求,现有动画类无法满足时使用 |
QVariantAnimation | 通用插值动画类,支持多种类型(如整数、浮点数、颜色等)的值变化,提供 valueChanged 信号 | 数值渐变(如颜色渐变、大小调整等) |
QPropertyAnimation | 操作 QObject 的属性动画,直接绑定属性名称(如 "pos" 、"size" ),支持平滑插值和缓动曲线 | 对象的移动、缩放、透明度变化等动画效果 |
9.4 四、对比总结
- QAbstractAnimation:框架层面的基类,提供动画生命周期管理
- QVariantAnimation:可插值任何数值,适合自定义数值动画
- QPropertyAnimation:最常用,直接作用于对象属性,易于上手
根据需求选择合适的类:若只是要动画化控件的属性,用 QPropertyAnimation
;若需要自定义插值逻辑,可用 QVariantAnimation
;若需要从更底层控制动画流程,可以继承 QAbstractAnimation
。
通过上述内容,应该对 Qt 动画的整体框架和常用类有了比较系统的认识。可以先从最简单的 QPropertyAnimation
入手,为按钮或窗口做移动、大小、透明度的动画,再逐步尝试组合动画(顺序或并行),最后再根据需要,学习并使用 QTimeLine
、QEasingCurve
等更高级或更灵活的功能。
相关文章:

qt-C++笔记之动画框架(Qt Animation Framework)入门
qt-C笔记之动画框架(Qt Animation Framework)入门 code review! 在 Linux 平台上,使用 C 和 Qt 框架实现动画是一个非常好的选择。Qt 提供了强大的动画框架(Qt Animation Framework),使得动画的实现变得简单高效。下面将介绍 Qt …...
C++26 函数契约(Contract)概览
文章目录 1. 什么是契约编程?契约编程的三大核心: 2. C26 契约编程的语法语法示例 3. 契约检查模式3.1. default 模式3.2. audit 模式3.3. axiom 模式检查模式的设置 4. 契约编程与传统 assert 的区别示例对比 5. 契约编程的应用场景6. 注意事项7. 示例: 带契约的矩形面积计算…...

Flink CDC 自定义函数处理 SQLServer XML类型数据 映射 doris json字段方案
Flink CDC 自定义函数处理 SQLServer XML类型数据方案 1. 背景 因业务使用SQLServer数据库,CDC同步到doris 数仓。对于SQLServer xml类型,doris没有相应的字段对应, 可以使用json来存储xml数据。需要进行一步转换。从 flink 自定义函数入手…...
F.interpolate函数
F.interpolate 是 PyTorch 中用于对张量(通常是图像数据)进行插值操作的函数,常用于调整张量的大小,例如改变图像的分辨率。它支持多种插值方法,包括最近邻插值、双线性插值和三次插值等。 语法 torch.nn.functional…...
华为交换机---自动备份配置到指定ftp/sftp服务器
华为交换机—自动备份配置到指定ftp服务器 需求 交换机配置修改后及时备份相关配置,每次配置变化后需要在1分钟后自动进行保存,并且将配置上传至FTP服务器;每隔30分钟,交换机自动把配置上传到FTP服务器。 1、定时保存新配置的时间间隔为*分钟(1天=1440),默认为30分钟(…...

nginx学习之路-nginx配置https服务器
文章目录 1. 生成证书2. 配置证书1. 拷贝证书文件2. 修改conf/nginx.conf文件内容 3. 查看效果1. 重载配置2. 访问 1. 生成证书 在linux系统下执行,使用openssl命令。(windows环境也可以使用cmder) # 1. 生成私钥 server2025.key(无密码保护…...

UCAS 24秋网络认证技术 CH10 SSL 复习
TLS字段、参数含义要了解每个消息是什么意思 基本方式只验证服务端,服务端有证书,变形方式加上验证客户端TLS1.3区别 协商过程 背景 Record层使用的各种加密算法参数,均由Handshake协议协商获得。 具体过程 随机数交换 Client/Server相互…...

【linux内核分析-存储】EXT4源码分析之“文件删除”原理【七万字超长合并版】(源码+关键细节分析)
EXT4源码分析之“文件删除”原理【七万字超长合并版】(源码关键细节分析),详细的跟踪了ext4文件删除的核心调用链,分析关键函数的细节,解答了开篇中提出的三个核心疑问。 文章目录 提示前言全文重点索引1.源码解析1.1 …...
代码随想录 day62 第十一章 图论part11
第十一章:图论part11 Floyd 算法精讲 Floyd 算法代码很简单,但真正理解起原理 还是需要花点功夫,大家在看代码的时候,会发现 Floyd 的代码很简单,甚至看一眼就背下来了,但我为了讲清楚原理,本…...

springboot571基于协同过滤算法的私人诊所管理系统(论文+源码)_kaic
摘 要 随着时代的发展,人们的生活方式得到巨大的改变,从而慢慢地出现了大量私人诊所信息,私人诊所信息管理需要一个现代化的管理系统,进行私人诊所的管理。 私人诊所管理系统的开发就是为了解决私人诊所信息管理的问题࿰…...

Uniapp Android 本地离线打包(详细流程)
一、简介 App 离线 SDK 暂时不支持 Kotlin,未来不清楚。 uniapp 提供了 云打包 与 本地打包 两种方案,云打包 需要排队且还有次数限制,本地打包 则就没有这些限制,而且会 本地打包 对开发 原生插件 有很大的帮助。 细节&#x…...

vite+vue3动态引入资源文件(问题已解决但离了个大谱)
教程很详细,直接上代码 解决方法(赶时间的小友理解下这函数就能解决问题了,就是处理了下路径,运气不好遇到问题再回来也不迟🤣🤣🤣) const getSvgUrl (name) > {// name: svg_1…...

通过 4 种方式快速将音乐从 iPod 传输到 Android
概括 在 iPod 上听音乐很酷,但是当您拥有最新的 Android 手机时,也许您想在新手机上欣赏 iPod 音乐。那么,你的计划是什么?如何将音乐从 iPod 传输到 Android? 如果您担心这个问题,请看看下面的方法。他们…...

ArcGIS中怎么把数据提取到指定范围(裁剪、掩膜提取)
最近,经常能收到怎么把数据提取到指定范围、栅格数据怎么裁剪、矢量数据怎么裁剪、栅格数据怎么掩膜提取的咨询。 下面是我对这个问题的解决思路: 对于矢量数据: ①首先把数据加载进来 ②软件界面上面的工具栏找到→地理处理→裁剪&#x…...

【Vaadin flow 实战】第3讲-快速上手构建VaadinFlow+Springboot的全栈web项目
快速构建VaadinFlowSpringboot的全栈web项目 温馨提示,本文讲解比较精炼,主要以快速上手开发为主。 官方提供了与本文类似的教程讲解,地址https://vaadin.com/docs/latest/getting-started 1访问vaadin官方提供的start网站(类似于 spring i…...
HBase Cassandra的部署和操作
目录 一.数据库的部署与配置 二.使用命令访问数据库 三.数据库的设计 四.编程实现数据库的访问 一.数据库的部署与配置 1.在单个节点上对进行数据库的单机部署 (1)下载apache-cassandra-4.1.7-…...

用户界面软件01
Jens Coldewey 著,Tom.X 译 本文中的模式语言逐步深入地探讨用户界面架构的设计,它基于人机工程学,足以形成一套完整的体系。如果你对这方面有兴趣,请参考[Tog92],[Coo95]和[Col95]。 本文不讨论用户界面的布局&…...
【云原生】Docker Compose 从入门到实战使用详解
目录 一、前言 二、Docker Compose 介绍 2.1 Docker Compose概述 2.2 Docker Compose特点 2.3 Docker Compose使用场景 三、Docker Compose 安装 3.1 安装docker环境 3.2 Docker Compose安装方式一 3.2.1 下载最新版 3.2.2 设置权限 3.2.3 设置软链接 3.2.4 查看版本…...
【ShuQiHere】使用 SCP 进行安全文件传输
【ShuQiHere】🚀 在日常的开发和运维工作中,文件传输是一个常见的任务。scp(Secure Copy)是一个基于 SSH 协议的文件传输工具,能够在本地和远程主机之间安全地复制文件和目录。本文将详细介绍 scp 的使用方法…...

海康威视H5player问题汇总大全
由于除了要支持Windows平台,还要支持国产系统的平台,这时就用到了H5player,但是这个在使用调试的时候会遇到各种各样的问题,便在此分享一下,供大家分享!!! 问题一:Unexp…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...