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

Qt 实现自定义截图工具

目录

  • Qt 实现自定义截图工具
    • 实现效果图
    • PrintScreen 类介绍
      • PrintScreen 类的主要特性
    • 逐步实现
      • 第一步:类定义
      • 第二步:初始化截图窗口
      • 第三步:处理鼠标事件
      • 第四步:计算截图区域
      • 第五步:捕获和保存图像
    • 完整代码
      • PrintScreen.h
      • PrintScreen.cpp
      • MainWindow.h
      • MainWindow.cpp
      • main.cpp

Qt 实现自定义截图工具

本文使用Qt框架从头开始创建一个简单的屏幕截图工具。

实现效果图

截图按钮:
截图按钮
选取截图初始状态:
选取截图初始状态
选取截图区域:
选取截图区域
截图保存界面:
截图保存界面

PrintScreen 类介绍

PrintScreen 类是一个自定义的 QWidget,允许用户捕捉屏幕上的任意区域。本教程将展示如何利用 Qt 的多功能库来实现这一功能。

PrintScreen 类的主要特性

  • 全屏覆盖,用于选择要捕捉的屏幕区域。
  • 通过鼠标互动选择定义捕捉区域。
  • 拖放调整选定区域。
  • 将捕获的区域保存为图片文件。

逐步实现

第一步:类定义

首先定义继承自 QWidgetPrintScreen 类。包含必要的 Qt 头文件,并声明我们的函数和成员变量。

#include <QWidget>
#include <QPainter>/*** @brief The PrintScreen class* @param 区域截屏功能*/
class PrintScreen : public QWidget
{Q_OBJECT
public:PrintScreen(QWidget *parent = nullptr);~PrintScreen();private:/*** @brief 初始化截图窗口的背景和尺寸*/void InitWindow();/*** @brief 根据起始点和终止点计算矩形区域* @param beginPoint 矩形区域的起始点* @param endPoint 矩形区域的终止点* @return 返回根据两点计算出的 QRect 对象*/QRect GetRect(const QPoint &beginPoint, const QPoint &endPoint);protected:// 事件处理方法void mousePressEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent* event);void mouseReleaseEvent(QMouseEvent *event);void keyPressEvent(QKeyEvent *event);void paintEvent(QPaintEvent *event);private:// 成员变量bool m_isMousePress = false;     // 是否按下鼠标bool m_captureComplete = false;  // 截图是否完成bool m_isDragging = false;       // 是否正在拖动截图区域QPixmap m_loadPixmap;    // 加载的屏幕截图QPixmap m_capturePixmap; // 截取的屏幕区域int m_screenWidth;       // 屏幕宽度int m_screenHeight;      // 屏幕高度QPoint m_beginPoint;     // 截图开始点QPoint m_endPoint;       // 截图结束点QPoint m_originalBegin;  // 原始截图开始点QPoint m_originalEnd;    // 原始截图结束点QPoint m_dragPosition;   // 拖动时的鼠标位置QPainter m_painter;      // 绘图器对象
};

第二步:初始化截图窗口

InitWindow 方法设置窗口属性,如全屏模式、无边框窗口提示和鼠标跟踪。它还捕获整个屏幕并存储在 m_loadPixmap 中。

void PrintScreen::InitWindow()
{// 启用鼠标跟踪this->setMouseTracking(true);// 设置无边框窗口this->setWindowFlags(Qt::FramelessWindowHint);// 设置窗口为激活状态和全屏模式setWindowState(Qt::WindowActive | Qt::WindowFullScreen);// 确保关闭时自动删除setAttribute(Qt::WA_DeleteOnClose);// 获取主屏幕QScreen *screen = QApplication::primaryScreen();// 抓取整个屏幕内容m_loadPixmap = screen->grabWindow(QApplication::desktop()->winId());// 设置屏幕宽度、高度m_screenWidth = m_loadPixmap.width();m_screenHeight = m_loadPixmap.height();
}

第三步:处理鼠标事件

鼠标事件对于定义捕获区域至关重要。mousePressEventmouseMoveEventmouseReleaseEvent 处理捕获区域的开始、调整和最终确定。

void PrintScreen::mousePressEvent(QMouseEvent *event)
{// 按下右键 关闭截图窗口if (event->button() == Qt::RightButton){close();}// 按下左键else if (event->button() == Qt::LeftButton){if (m_captureComplete && QRect(m_beginPoint, m_endPoint).contains(event->pos())){m_isDragging = true;                          // 开始拖动m_dragPosition = event->pos() - m_beginPoint; // 计算开始拖动位置}else{m_isMousePress = true;       // 鼠标被按下m_isDragging = false;m_beginPoint = event->pos(); // 记录开始点m_originalBegin = m_beginPoint;}}
}void PrintScreen::mouseMoveEvent(QMouseEvent *event)
{// 鼠标按下且截图未完成if (m_isMousePress && !m_captureComplete){m_endPoint = event->pos(); // 更新结束点}// 正在拖动else if (m_isDragging){QPoint newTopLeft = event->pos() - m_dragPosition;QPoint offset = newTopLeft - m_beginPoint;m_beginPoint += offset;m_endPoint += offset;}update();
}void PrintScreen::mouseReleaseEvent(QMouseEvent *event)
{// 鼠标释放且截图未完成if (m_isMousePress && !m_captureComplete){m_endPoint = event->pos();  // 设置结束点m_isMousePress = false;     // 重置鼠标按下状态m_captureComplete = true;   // 标记截图完成update();}// 释放时正在拖动else if (m_isDragging){m_isDragging = false;}update();
}

第四步:计算截图区域

GetRect 方法接收两个参数:beginPointendPoint,这两个点是用户通过鼠标操作定义的截图区域的开始和结束位置。此方法用于计算并返回一个 QRect 对象,该对象表示屏幕上要截取的矩形区域。

QRect PrintScreen::GetRect(const QPoint &beginPoint, const QPoint &endPoint)
{int x = std::min(beginPoint.x(), endPoint.x());int y = std::min(beginPoint.y(), endPoint.y());int width = std::abs(beginPoint.x() - endPoint.x());int height = std::abs(beginPoint.y() - endPoint.y());if (width == 0) width = 1;   // 确保宽度至少为1像素if (height == 0) height = 1; // 确保高度至少为1像素return QRect(x, y, width, height);
}

解释:

  • 计算 x 和 y 坐标:使用 std::min 函数确定矩形的左上角 x 和 y 坐标,这保证了无论用户如何拖动鼠标(从左到右或从右到左),都能正确计算出矩形的位置。
  • 计算宽度和高度:使用 std::abs 函数计算宽度和高度,确保值总是正数。如果计算结果为0(即起点和终点在同一直线上),则将宽度或高度设为1像素,确保矩形至少有最小的可见尺寸。

第五步:捕获和保存图像

paintEvent 方法在屏幕上绘制捕获的区域。keyPressEvent 监听回车键以触发保存捕获的图像。

void PrintScreen::paintEvent(QPaintEvent *event)
{Q_UNUSED(event)m_painter.begin(this);                                           // 开始绘制QColor shadowColor(0, 0, 0, 100);                                // 半透明遮罩颜色m_painter.setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::FlatCap)); // 设置画笔m_painter.drawPixmap(0, 0, m_loadPixmap);                        // 绘制加载的屏幕截图m_painter.fillRect(m_loadPixmap.rect(), shadowColor);            // 绘制半透明遮罩QRect selectedRect = GetRect(m_beginPoint, m_endPoint);          // 获取选择区域m_capturePixmap = m_loadPixmap.copy(selectedRect);               // 截取选择区域的屏幕截图m_painter.drawPixmap(selectedRect.topLeft(), m_capturePixmap);   // 绘制截取的区域m_painter.drawRect(selectedRect);                                // 绘制选择区域的边框m_painter.end();                                                 // 结束绘制
}
void PrintScreen::keyPressEvent(QKeyEvent *event)
{// 按下回车键if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return){// 保存图片QString filePath = QFileDialog::getSaveFileName(nullptr, "保存图片",QString(),"Images (*.png *.jpg)");if(!filePath.isEmpty()){m_capturePixmap.save(filePath); // 保存截图到文件}close();}
}

完整代码

PrintScreen.h

#ifndef PRINTSCREEN_H
#define PRINTSCREEN_H#include <QWidget>
#include <QPainter>/*** @brief The PrintScreen class* @param 区域截屏功能*/
class PrintScreen : public QWidget
{Q_OBJECT
public:PrintScreen(QWidget *parent = nullptr);~PrintScreen();private:/*** @brief 初始化截图窗口的背景和尺寸*/void InitWindow();/*** @brief 根据起始点和终止点计算矩形区域* @param beginPoint 矩形区域的起始点* @param endPoint 矩形区域的终止点* @return 返回根据两点计算出的 QRect 对象*/QRect GetRect(const QPoint &beginPoint, const QPoint &endPoint);protected:// 事件处理方法void mousePressEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent* event);void mouseReleaseEvent(QMouseEvent *event);void keyPressEvent(QKeyEvent *event);void paintEvent(QPaintEvent *event);private:// 成员变量bool m_isMousePress = false;     // 是否按下鼠标bool m_captureComplete = false;  // 截图是否完成bool m_isDragging = false;       // 是否正在拖动截图区域QPixmap m_loadPixmap;    // 加载的屏幕截图QPixmap m_capturePixmap; // 截取的屏幕区域int m_screenWidth;       // 屏幕宽度int m_screenHeight;      // 屏幕高度QPoint m_beginPoint;     // 截图开始点QPoint m_endPoint;       // 截图结束点QPoint m_originalBegin;  // 原始截图开始点QPoint m_originalEnd;    // 原始截图结束点QPoint m_dragPosition;   // 拖动时的鼠标位置QPainter m_painter;      // 绘图器对象
};#endif // PRINTSCREEN_H

PrintScreen.cpp

#include "PrintScreen.h"#include <QScreen>
#include <QFileDialog>
#include <QMouseEvent>
#include <QApplication>
#include <QDesktopWidget>PrintScreen::PrintScreen(QWidget *parent): QWidget{parent}
{InitWindow();
}PrintScreen::~PrintScreen(){}void PrintScreen::InitWindow()
{// 启用鼠标跟踪this->setMouseTracking(true);// 设置无边框窗口this->setWindowFlags(Qt::FramelessWindowHint);// 设置窗口为激活状态和全屏模式setWindowState(Qt::WindowActive | Qt::WindowFullScreen);// 确保关闭时自动删除setAttribute(Qt::WA_DeleteOnClose);// 获取主屏幕QScreen *screen = QApplication::primaryScreen();// 抓取整个屏幕内容m_loadPixmap = screen->grabWindow(QApplication::desktop()->winId());// 设置屏幕宽度、高度m_screenWidth = m_loadPixmap.width();m_screenHeight = m_loadPixmap.height();
}QRect PrintScreen::GetRect(const QPoint &beginPoint, const QPoint &endPoint)
{int x = std::min(beginPoint.x(), endPoint.x());int y = std::min(beginPoint.y(), endPoint.y());int width = std::abs(beginPoint.x() - endPoint.x());int height = std::abs(beginPoint.y() - endPoint.y());if (width == 0) width = 1;   // 确保宽度至少为1像素if (height == 0) height = 1; // 确保高度至少为1像素return QRect(x, y, width, height);
}void PrintScreen::mousePressEvent(QMouseEvent *event)
{// 按下右键 关闭截图窗口if (event->button() == Qt::RightButton){close();}// 按下左键else if (event->button() == Qt::LeftButton){if (m_captureComplete && QRect(m_beginPoint, m_endPoint).contains(event->pos())){m_isDragging = true;                          // 开始拖动m_dragPosition = event->pos() - m_beginPoint; // 计算开始拖动位置}else{m_isMousePress = true;       // 鼠标被按下m_isDragging = false;m_beginPoint = event->pos(); // 记录开始点m_originalBegin = m_beginPoint;}}
}void PrintScreen::mouseMoveEvent(QMouseEvent *event)
{// 鼠标按下且截图未完成if (m_isMousePress && !m_captureComplete){m_endPoint = event->pos(); // 更新结束点}// 正在拖动else if (m_isDragging){QPoint newTopLeft = event->pos() - m_dragPosition;QPoint offset = newTopLeft - m_beginPoint;m_beginPoint += offset;m_endPoint += offset;}update();
}void PrintScreen::mouseReleaseEvent(QMouseEvent *event)
{// 鼠标释放且截图未完成if (m_isMousePress && !m_captureComplete){m_endPoint = event->pos();  // 设置结束点m_isMousePress = false;     // 重置鼠标按下状态m_captureComplete = true;   // 标记截图完成update();}// 释放时正在拖动else if (m_isDragging){m_isDragging = false;}update();
}void PrintScreen::keyPressEvent(QKeyEvent *event)
{// 按下回车键if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return){// 保存图片QString filePath = QFileDialog::getSaveFileName(nullptr, "保存图片",QString(),"Images (*.png *.jpg)");if(!filePath.isEmpty()){m_capturePixmap.save(filePath); // 保存截图到文件}close();}
}void PrintScreen::paintEvent(QPaintEvent *event)
{Q_UNUSED(event)m_painter.begin(this);                                           // 开始绘制QColor shadowColor(0, 0, 0, 100);                                // 半透明遮罩颜色m_painter.setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::FlatCap)); // 设置画笔m_painter.drawPixmap(0, 0, m_loadPixmap);                        // 绘制加载的屏幕截图m_painter.fillRect(m_loadPixmap.rect(), shadowColor);            // 绘制半透明遮罩QRect selectedRect = GetRect(m_beginPoint, m_endPoint);          // 获取选择区域m_capturePixmap = m_loadPixmap.copy(selectedRect);               // 截取选择区域的屏幕截图m_painter.drawPixmap(selectedRect.topLeft(), m_capturePixmap);   // 绘制截取的区域m_painter.drawRect(selectedRect);                                // 绘制选择区域的边框m_painter.end();                                                 // 结束绘制
}

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QPushButton>#include "PrintScreen.h"class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:QPushButton *m_screenBtn;PrintScreen *m_printScree;// QObject interface
public:bool eventFilter(QObject *watched, QEvent *event);
};
#endif // MAINWINDOW_H

MainWindow.cpp

#include "MainWindow.h"
#include <QLayout>
#include <QMouseEvent>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), m_screenBtn(new QPushButton("截图", this))
{// 设置中心窗口setCentralWidget(m_screenBtn);// 安装事件过滤器m_screenBtn->installEventFilter(this);// 隐藏标题栏setWindowFlags(Qt::FramelessWindowHint);resize(150, 50);
}MainWindow::~MainWindow() {}bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{if (watched == m_screenBtn && event->type() == QEvent::MouseButtonPress){QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);if (mouseEvent->button() == Qt::RightButton){close();return true;}else if (mouseEvent->button() == Qt::LeftButton){m_printScree = new PrintScreen();m_printScree->show();return true;}}return QMainWindow::eventFilter(watched, event);
}

main.cpp

#include "MainWindow.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}

相关文章:

Qt 实现自定义截图工具

目录 Qt 实现自定义截图工具实现效果图PrintScreen 类介绍PrintScreen 类的主要特性 逐步实现第一步&#xff1a;类定义第二步&#xff1a;初始化截图窗口第三步&#xff1a;处理鼠标事件第四步&#xff1a;计算截图区域第五步&#xff1a;捕获和保存图像 完整代码PrintScreen.…...

第15-05章:获取运行时类的完整结构

我的后端学习大纲 我的Java学习大纲 6.1.第一组方法API: 1.API列表&#xff1a;java.lang.Class 类&#xff1a; 2.代码测试&#xff1a; public class ReflectionUtils{ puvblic static void main(String[] args){}// 第一组Testpublic void api_01{//上面截图的代码......…...

【Kubernetes】K8s 的鉴权管理(二):基于属性 / 节点 / Webhook 的访问控制

K8s 的鉴权管理&#xff08;二&#xff09;&#xff1a;基于属性 / 节点 / Webhook 的访问控制 1.基于属性的访问控制&#xff08;ABAC 鉴权&#xff09;2.基于节点的访问控制&#xff08;node 鉴权&#xff09;2.1 读取操作2.2 写入操作 3.基于 Webhook 的访问控制3.1 基于 We…...

Java面试、技巧、问题、回复,资源面面观

入门 先了解一下面试流程 复习 Java 基础知识&#xff1a; 温习 Java 编程的核心概念&#xff0c;包括数据类型、变量、循环、数组和面向对象的编程原则。数据结构和算法&#xff1a; 加强您对 Java 编程中使用的基本数据结构和算法的理解。练习编码&#xff1a; 在各种平台上解…...

深入理解Elasticsearch的`_source`字段与索引优化

在Elasticsearch (ES) 中&#xff0c;_source字段是一个关键组件&#xff0c;它不仅决定了数据的存储方式&#xff0c;还影响到查询时返回的内容。在某些场景下&#xff0c;我们可以通过配置_source来优化存储和性能&#xff0c;尤其是当我们希望减少存储空间或避免返回某些字段…...

Pikachu靶场

先来点鸡汤&#xff0c;少就是多&#xff0c;慢就是快。 环境搭建 攻击机kali 192.168.146.140 靶机win7 192.168.146.161 下载zip&#xff0c;pikachu - GitCode 把下载好的pikachu-master&#xff0c;拖进win7&#xff0c;用phpstudy打开网站根目录&#xff0c;.....再用…...

TS axios封装

方式一 service/request/request.ts import axios from axios import { ElLoading } from element-plus import type { AxiosRequestConfig, AxiosInstance, AxiosResponse } from axios import type { ILoadingInstance } from element-plus/lib/el-loading/src/loading.typ…...

学会使用西门子博途Startdrive中的测量功能

工程师在驱动调试过程中&#xff0c;往往需要对驱动系统的性能进行分析及优化&#xff0c;比如说借助于调试软件中的驱动器测量功能&#xff0c;可以得到驱动系统的阶跃响应、波特图等&#xff0c;以此为依据工程师可以调整速度控制器、电流控制器的相关参数&#xff0c;使驱动…...

Spring Security认证与授权

1 Spring Security介绍 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。由于它是Spring生态系统中的一员&#xff0c;因此它伴随着整个Spring生态系统不断修正、升级&#xff0c;在spring boot项目中加入springsecurity更是…...

速通GPT:Improving Language Understanding by Generative Pre-Training全文解读

文章目录 速通GPT系列几个重要概念1、微调的具体做法2、任务感知输入变换3、判别式训练模型 Abstract概括分析和观点1. 自然语言理解中的数据问题2. 生成预训练和监督微调的结合3. 任务感知输入变换4. 模型的强大性能 Introduction概括分析和观点1. 自然语言理解的挑战在于对标…...

软件质量保证例题

答案&#xff1a;D 软件质量保证 功能性 适合性 准确性 互操作性 安全保密性 依从性 可靠性 成熟性 容错性 易恢复性 易用性 易理解性 易学性 易操作性 效率 时间特性 资源利用性 维护性 易分析性 易改变性 稳定性 易测试性 可移植性 适应性 易安装性 一致性 易替换…...

动态规划算法---04.斐波那契数列模型_解码方法_C++

题目链接&#xff1a;91. 解码方法 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/decode-ways/description/ 一、题目解析 题目&#xff1a; 题目大意&#xff1a;从题目中我们可以知道&#xff0c;解码就是在字符串s中由‘1’到‘26’的字符可以转化…...

crm如何做私域运营?

流量获取的挑战日益增加&#xff0c;客户线索成本高、客户资源流失严重、转化率低&#xff0c;因此&#xff0c;私域流量管理已成为关键。 当前挑战 1、公域流量难以整合&#xff1a;外部流量分散&#xff0c;难以有效汇总和沉淀。 2、私域运营体系缺失&#xff1a;缺乏有效沟…...

基于QGIS 3.16.0 的OSM路网矢量范围裁剪实战-以湖南省为例

目录 前言 一、相关数据介绍 1、OMS路网数据 2、路网数据 3、路网图层属性 二、按省域范围进行路网裁剪 1、裁剪范围制定 2、空间裁剪 3、裁剪结果 三、总结 前言 改革开放特别是党的十八大以来&#xff0c;我国公路发展取得了举世瞩目的成就。国家高速公路网由“7 射…...

WPF 手撸插件 八 依赖注入

本文内容大量参考了&#xff1a;https://www.cnblogs.com/Chary/p/11351457.html 而且这篇文章总结的非常好。 1、注意想使用Autofac&#xff0c;Autofac是一个轻量级、‌高性能的依赖注入&#xff08;‌DI&#xff09;‌框架&#xff0c;‌主要用于.NET应用程序的组件解耦和…...

走进低代码报表开发(一):探秘报表数据源

在前文当中&#xff0c;我们对勤研低代码平台的流程设计功能进行了介绍。接下来&#xff0c;让我们一同深入了解在企业日常运营中另一个极为常见的报表功能。在当今数字化时代&#xff0c;高效的报表生成对于企业的决策至关重要。勤研低代码开发平台能够以卓越的性能和便捷的操…...

代理服务器及其原理

代理服务器的代理可以分为正向代理和反向代理&#xff0c;本篇将讲解这两种代理方式的原理&#xff0c;以及对应的功能特点和应用场景。最后还对比和 NAT 和代理服务器的区别。 目录 正向代理 工作原理 功能特点 应用场景 反向代理 基本原理 应用场景 NAT和代理服务器…...

计算机毕业设计选题推荐-养老院管理系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...

免费SSL证书正在逐渐被淘汰,证书部署自动化的发展趋势即将到来!

目录 背景解决方案。1.使用自签证书&#xff08;浏览器报警、免费&#xff09;2.更换支持自签自续的CA机构&#xff08;免费&#xff09;3.付费选择CA机构 免费SSL证书正在逐渐被淘汰&#xff0c;证书部署自动化的发展趋势即将到来免费的SSL证书有以下弊端1.有效期短&#xff1…...

openVX加速-基本概念和简单代码实现

OpenVX 是一个用于计算机视觉和图像处理的跨平台加速标准库&#xff0c;旨在提高在异构平台&#xff08;如 CPU、GPU、DSP 等&#xff09;上的执行效率。OpenVX 提供了一组优化的、可移植的 API&#xff0c;用于加速常见的视觉算法&#xff0c;使开发者能够在不同硬件平台上实现…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

软件工程 期末复习

瀑布模型&#xff1a;计划 螺旋模型&#xff1a;风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合&#xff1a;模块内部功能紧密 模块之间依赖程度小 高内聚&#xff1a;指的是一个模块内部的功能应该紧密相关。换句话说&#xff0c;一个模块应当只实现单一的功能…...

面试高频问题

文章目录 &#x1f680; 消息队列核心技术揭秘&#xff1a;从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"&#xff1f;性能背后的秘密1.1 顺序写入与零拷贝&#xff1a;性能的双引擎1.2 分区并行&#xff1a;数据的"八车道高速公路"1.3 页缓存与批量处理…...