Qt 实现自定义截图工具
目录
- Qt 实现自定义截图工具
- 实现效果图
- PrintScreen 类介绍
- PrintScreen 类的主要特性
- 逐步实现
- 第一步:类定义
- 第二步:初始化截图窗口
- 第三步:处理鼠标事件
- 第四步:计算截图区域
- 第五步:捕获和保存图像
- 完整代码
- PrintScreen.h
- PrintScreen.cpp
- MainWindow.h
- MainWindow.cpp
- main.cpp
Qt 实现自定义截图工具
本文使用Qt框架从头开始创建一个简单的屏幕截图工具。
实现效果图
截图按钮:

选取截图初始状态:

选取截图区域:

截图保存界面:

PrintScreen 类介绍
PrintScreen 类是一个自定义的 QWidget,允许用户捕捉屏幕上的任意区域。本教程将展示如何利用 Qt 的多功能库来实现这一功能。
PrintScreen 类的主要特性
- 全屏覆盖,用于选择要捕捉的屏幕区域。
- 通过鼠标互动选择定义捕捉区域。
- 拖放调整选定区域。
- 将捕获的区域保存为图片文件。
逐步实现
第一步:类定义
首先定义继承自 QWidget 的 PrintScreen 类。包含必要的 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();
}
第三步:处理鼠标事件
鼠标事件对于定义捕获区域至关重要。mousePressEvent、mouseMoveEvent 和 mouseReleaseEvent 处理捕获区域的开始、调整和最终确定。
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 方法接收两个参数:beginPoint 和 endPoint,这两个点是用户通过鼠标操作定义的截图区域的开始和结束位置。此方法用于计算并返回一个 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 类的主要特性 逐步实现第一步:类定义第二步:初始化截图窗口第三步:处理鼠标事件第四步:计算截图区域第五步:捕获和保存图像 完整代码PrintScreen.…...
第15-05章:获取运行时类的完整结构
我的后端学习大纲 我的Java学习大纲 6.1.第一组方法API: 1.API列表:java.lang.Class 类: 2.代码测试: public class ReflectionUtils{ puvblic static void main(String[] args){}// 第一组Testpublic void api_01{//上面截图的代码......…...
【Kubernetes】K8s 的鉴权管理(二):基于属性 / 节点 / Webhook 的访问控制
K8s 的鉴权管理(二):基于属性 / 节点 / Webhook 的访问控制 1.基于属性的访问控制(ABAC 鉴权)2.基于节点的访问控制(node 鉴权)2.1 读取操作2.2 写入操作 3.基于 Webhook 的访问控制3.1 基于 We…...
Java面试、技巧、问题、回复,资源面面观
入门 先了解一下面试流程 复习 Java 基础知识: 温习 Java 编程的核心概念,包括数据类型、变量、循环、数组和面向对象的编程原则。数据结构和算法: 加强您对 Java 编程中使用的基本数据结构和算法的理解。练习编码: 在各种平台上解…...
深入理解Elasticsearch的`_source`字段与索引优化
在Elasticsearch (ES) 中,_source字段是一个关键组件,它不仅决定了数据的存储方式,还影响到查询时返回的内容。在某些场景下,我们可以通过配置_source来优化存储和性能,尤其是当我们希望减少存储空间或避免返回某些字段…...
Pikachu靶场
先来点鸡汤,少就是多,慢就是快。 环境搭建 攻击机kali 192.168.146.140 靶机win7 192.168.146.161 下载zip,pikachu - GitCode 把下载好的pikachu-master,拖进win7,用phpstudy打开网站根目录,.....再用…...
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中的测量功能
工程师在驱动调试过程中,往往需要对驱动系统的性能进行分析及优化,比如说借助于调试软件中的驱动器测量功能,可以得到驱动系统的阶跃响应、波特图等,以此为依据工程师可以调整速度控制器、电流控制器的相关参数,使驱动…...
Spring Security认证与授权
1 Spring Security介绍 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。由于它是Spring生态系统中的一员,因此它伴随着整个Spring生态系统不断修正、升级,在spring boot项目中加入springsecurity更是…...
速通GPT:Improving Language Understanding by Generative Pre-Training全文解读
文章目录 速通GPT系列几个重要概念1、微调的具体做法2、任务感知输入变换3、判别式训练模型 Abstract概括分析和观点1. 自然语言理解中的数据问题2. 生成预训练和监督微调的结合3. 任务感知输入变换4. 模型的强大性能 Introduction概括分析和观点1. 自然语言理解的挑战在于对标…...
软件质量保证例题
答案:D 软件质量保证 功能性 适合性 准确性 互操作性 安全保密性 依从性 可靠性 成熟性 容错性 易恢复性 易用性 易理解性 易学性 易操作性 效率 时间特性 资源利用性 维护性 易分析性 易改变性 稳定性 易测试性 可移植性 适应性 易安装性 一致性 易替换…...
动态规划算法---04.斐波那契数列模型_解码方法_C++
题目链接:91. 解码方法 - 力扣(LeetCode)https://leetcode.cn/problems/decode-ways/description/ 一、题目解析 题目: 题目大意:从题目中我们可以知道,解码就是在字符串s中由‘1’到‘26’的字符可以转化…...
crm如何做私域运营?
流量获取的挑战日益增加,客户线索成本高、客户资源流失严重、转化率低,因此,私域流量管理已成为关键。 当前挑战 1、公域流量难以整合:外部流量分散,难以有效汇总和沉淀。 2、私域运营体系缺失:缺乏有效沟…...
基于QGIS 3.16.0 的OSM路网矢量范围裁剪实战-以湖南省为例
目录 前言 一、相关数据介绍 1、OMS路网数据 2、路网数据 3、路网图层属性 二、按省域范围进行路网裁剪 1、裁剪范围制定 2、空间裁剪 3、裁剪结果 三、总结 前言 改革开放特别是党的十八大以来,我国公路发展取得了举世瞩目的成就。国家高速公路网由“7 射…...
WPF 手撸插件 八 依赖注入
本文内容大量参考了:https://www.cnblogs.com/Chary/p/11351457.html 而且这篇文章总结的非常好。 1、注意想使用Autofac,Autofac是一个轻量级、高性能的依赖注入(DI)框架,主要用于.NET应用程序的组件解耦和…...
走进低代码报表开发(一):探秘报表数据源
在前文当中,我们对勤研低代码平台的流程设计功能进行了介绍。接下来,让我们一同深入了解在企业日常运营中另一个极为常见的报表功能。在当今数字化时代,高效的报表生成对于企业的决策至关重要。勤研低代码开发平台能够以卓越的性能和便捷的操…...
代理服务器及其原理
代理服务器的代理可以分为正向代理和反向代理,本篇将讲解这两种代理方式的原理,以及对应的功能特点和应用场景。最后还对比和 NAT 和代理服务器的区别。 目录 正向代理 工作原理 功能特点 应用场景 反向代理 基本原理 应用场景 NAT和代理服务器…...
计算机毕业设计选题推荐-养老院管理系统-Java/Python项目实战
✨作者主页:IT毕设梦工厂✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...
免费SSL证书正在逐渐被淘汰,证书部署自动化的发展趋势即将到来!
目录 背景解决方案。1.使用自签证书(浏览器报警、免费)2.更换支持自签自续的CA机构(免费)3.付费选择CA机构 免费SSL证书正在逐渐被淘汰,证书部署自动化的发展趋势即将到来免费的SSL证书有以下弊端1.有效期短࿱…...
openVX加速-基本概念和简单代码实现
OpenVX 是一个用于计算机视觉和图像处理的跨平台加速标准库,旨在提高在异构平台(如 CPU、GPU、DSP 等)上的执行效率。OpenVX 提供了一组优化的、可移植的 API,用于加速常见的视觉算法,使开发者能够在不同硬件平台上实现…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...
系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...
