qt学习:截图+键盘事件
效果
- 生成一个透明无边框全屏的窗口,然后按ctrl+b键就可以选择区域进行截图保存
步骤
- 新建一个项目
- 新建一个ctrlb类继承QMainWindow
- 新建一个CaptureScreen类继承QWidget
- 在main中启动ctrlb类
代码
ctrlb类.cpp
#include "ctrlb.h"
#include "capturescreen.h"
#include <QKeyEvent>
#include <QPixmap>
#include <QFileDialog>
#include <QProcess>
#include <QDebug>
#include <QFile>
#include <QTextStream>ctrlb::ctrlb(QWidget *parent): QMainWindow(parent) {}// 按键事件
void ctrlb::keyPressEvent(QKeyEvent *event) {if (event->key() == Qt::Key_B && event->modifiers() == Qt::ControlModifier) {triggerScreenshot();}
}
// 截图操作
void ctrlb::triggerScreenshot() {// 定义截图对象CaptureScreen *capture = new CaptureScreen();// 调用 close() 函数或用户点击关闭按钮时,窗口对象会被自动销毁capture->setAttribute(Qt::WA_DeleteOnClose); // 当完成截图操作后,会发送信号触发保存图片connect(capture, &CaptureScreen::signalCompleteCature, this, &ctrlb::handleScreenshot);// 显示截图窗口capture->show();
}
// 保存图片,参数是屏幕的截图
void ctrlb::handleScreenshot(const QPixmap &screenshot) {// 判断参数是否为空if (!screenshot.isNull()) {QString savePath = "check.jpg";if (!savePath.isEmpty()) {// 保存为用户指定的文件screenshot.save(savePath, "JPG"); }}}
ctrlb类.h
#ifndef CTRLB_H
#define CTRLB_H#include <QMainWindow>class ctrlb : public QMainWindow
{Q_OBJECT
public:explicit ctrlb(QWidget *parent = nullptr);protected:void keyPressEvent(QKeyEvent *event) override;private:void triggerScreenshot();private slots:// 保存图片槽函数void handleScreenshot(const QPixmap &screenshot);
};#endif // CTRLB_H
CaptureScreen类.cpp
#include "capturescreen.h"
#include <QApplication>
#include <QMouseEvent>
#include <QPixmap>
#include <QScreen>CaptureScreen::CaptureScreen(QWidget *parent): QWidget(parent), m_isMousePress(false)
{// 初始化窗口initWindow();//loadBackgroundPixmap();
}CaptureScreen::~CaptureScreen()
{}void CaptureScreen::initWindow()
{// 启用鼠标跟踪,移动的时候也会触发事件this->setMouseTracking(true);// 设置窗口为无边框模式this->setWindowFlags(Qt::FramelessWindowHint);// 设置窗口全屏显示setWindowState(Qt::WindowActive | Qt::WindowFullScreen);
}
// 抓取当前桌面内容作为背景快照
void CaptureScreen::loadBackgroundPixmap()
{// 获取当前主屏幕的 QScreen 对象QScreen *screen = QGuiApplication::primaryScreen();if (screen) {// 获取现在的整个屏幕m_loadPixmap = screen->grabWindow(0);}// 获取屏幕宽高m_screenwidth = m_loadPixmap.width();m_screenheight = m_loadPixmap.height();
}// 处理鼠标左键按下,记录起点位置
void CaptureScreen::mousePressEvent(QMouseEvent *event)
{// 判断是不是左键if (event->button() == Qt::LeftButton){// 画图标志m_isMousePress = true;// 记录起始位置m_beginPoint = event->pos();}return QWidget::mousePressEvent(event);
}// 处理鼠标移动,记录终点位置
void CaptureScreen::mouseMoveEvent(QMouseEvent* event)
{// 判断是否画图if (m_isMousePress){// 记录移动位置m_endPoint = event->pos();// 画矩形update();}return QWidget::mouseMoveEvent(event);
}// 处理鼠标松开,记录终点位置
void CaptureScreen::mouseReleaseEvent(QMouseEvent *event)
{// 记录结束位置m_endPoint = event->pos();// 结束画矩形m_isMousePress = false;return QWidget::mouseReleaseEvent(event);
}// 绘制事件
void CaptureScreen::paintEvent(QPaintEvent *event)
{// 初始化 QPainter 对象 m_painterm_painter.begin(this);// 半透明的黑色阴影,用于覆盖整个屏幕QColor shadowColor = QColor(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);// 如果鼠标正在移动,会绘制选中的矩形区域if (m_isMousePress){// 计算选区矩形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 CaptureScreen::keyPressEvent(QKeyEvent *event)
{// Esc 键退出截图;if (event->key() == Qt::Key_Escape){close();}// Enter键完成截图;if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter){// 保存截图为 JPG 格式QString savePath = "screenshot.jpg";if (!m_capturePixmap.isNull()) {// 保存为 JPG 格式m_capturePixmap.save(savePath, "JPG");}// 发送截图完成信号emit signalCompleteCature(m_capturePixmap);close();}
}// 计算一个矩形区域并返回
QRect CaptureScreen::getRect(const QPoint &beginPoint, const QPoint &endPoint)
{// 矩形的左上角坐标、宽度和高度int x, y, width, height;width = qAbs(beginPoint.x() - endPoint.x());height = qAbs(beginPoint.y() - endPoint.y());x = beginPoint.x() < endPoint.x() ? beginPoint.x() : endPoint.x();y = beginPoint.y() < endPoint.y() ? beginPoint.y() : endPoint.y();// 创建矩形对象QRect selectedRect = QRect(x, y, width, height);// 避免宽或高为零时拷贝截图有误,设置最小为1if (selectedRect.width() == 0){selectedRect.setWidth(1);}if (selectedRect.height() == 0){selectedRect.setHeight(1);}// 返回矩形对象return selectedRect;
}
CaptureScreen类.h
#ifndef CAPTURESCREEN_H
#define CAPTURESCREEN_H#include <QWidget>
#include <QPainter>class CaptureScreen : public QWidget
{Q_OBJECTpublic:CaptureScreen(QWidget *parent = 0);~CaptureScreen();Q_SIGNALS:void signalCompleteCature(QPixmap catureImage);private:void initWindow();void loadBackgroundPixmap();void mousePressEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent* event);void mouseReleaseEvent(QMouseEvent *event);void keyPressEvent(QKeyEvent *event);void paintEvent(QPaintEvent *event);QRect getRect(const QPoint &beginPoint, const QPoint &endPoint);private:bool m_isMousePress;// 判断鼠标是否移动和是否画矩形QPixmap m_loadPixmap;// 整个屏幕的图像QPixmap m_capturePixmap;// 框选的屏幕图像int m_screenwidth;// 屏幕的宽int m_screenheight;// 屏幕的高QPoint m_beginPoint, m_endPoint;// 起点和结束点坐标QPainter m_painter;// 画图对象
};#endif // CAPTURESCREEN_H
main
#include "mainwindow.h"#include <QApplication>
#include "ctrlb.h"
#include <QDebug>
#include <QWidget>int main(int argc, char *argv[])
{QApplication a(argc, argv);qDebug()<<"init";ctrlb w;// 设置无边框窗口w.setWindowFlags(Qt::FramelessWindowHint); // 全屏w.showFullScreen();// 背景透明w.setAttribute(Qt::WA_TranslucentBackground);// 设置透明度w.setWindowOpacity(1); w.show();return a.exec();
}
相关文章:
qt学习:截图+键盘事件
效果 生成一个透明无边框全屏的窗口,然后按ctrlb键就可以选择区域进行截图保存 步骤 新建一个项目新建一个ctrlb类继承QMainWindow新建一个CaptureScreen类继承QWidget在main中启动ctrlb类 代码 ctrlb类.cpp #include "ctrlb.h" #include "cap…...

Scala中Arry
import scala.collection.mutable.ArrayBuffer //Arry:数组 //可修改的:ArryBuffer //不可修改的:Arryobject Test_1118_2 {//可修改的:ArrayBufferdef main(args: Array[String]): Unit {//1.新建val arr1ArrayBuffer(1,2,3)//2.添加arr14a…...

学习threejs,使用AnimationMixer实现变形动画
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.AnimationMixer 动画…...

两大新兴开发语言大比拼:Move PK Rust
了解 Move 和 Rust 的差异有助于开发者根据项目的具体需求选择最合适的语言。选择不恰当的语言可能会导致项目后期出现技术债务。不同语言有其独特的优势。了解 Move 和 Rust 的差异可以帮助开发者拓展技术视野,发现不同语言在不同领域的应用潜力。 咱们直奔主题&a…...

基于一种基于OCR图像识别技术的发票采集管理系统及方法
本发明涉及了一种基于OCR图像识别技术的发票采集管理系统及方法,该系统的发票信息采集单元采集发票图片信息数据,OCR图像识别单元基于OCR图像识别技术并结合人工智能深度学习算法对发票图片信息数据进行识别读取以获得OCR图像识别结果,发票信…...

基于深度学习的车牌检测系统的设计与实现(安卓、YOLOV、CRNNLPRNet)+文档
💗博主介绍💗:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示:文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…...

JavaWeb——JS、Vue
目录 1.JavaScript a.概述 b.引入方式 c.JS的基础语法 d.JS函数 e.JS对象 f.JS事件监听 2.Vue a.概述 b.Vue常用指令 d.生命周期 1.JavaScript a.概述 JavaScript是一门跨平台、面向对象的脚本语言。是用来控制网页行为的,它能使网页可交互。JavaScript和…...

Springboot 整合 Java DL4J 构建股票预测系统
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...

ATmaga8单片机Pt100温度计源程序+Proteus仿真设计
目录 1、项目功能 2、仿真图 3、程序 资料下载地址:ATmaga8单片机Pt100温度计源程序Proteus仿真设计 1、项目功能 设计Pt100铂电阻测量温度的电路,温度测量范围是0-100摄氏度,要求LCD显示。画出电路图,标注元器件参数&am…...

FPGA通过MIPI CSI-2发送实时图像到RK3588,并HDMI显示
介绍FPGA通过MIPI CSI-2发送实时图像到RK3588,并HDMI显示。 FPGA本地产生动态图像模板,通过MIPI CSI-2接口发送到RK3588 MIPI CSI接口。RK3588注册成相机后,调用接口并在HDMI显示器上显示。 1、RK3588驱动调试 查看Media controller信息 Med…...

ELK8.15.4搭建开启安全认证
安装 Elastic :Elasticsearch,Kibana,Logstash 另外安装一个收集器filebeat 通过二进制安装包进行安装 创建一个专门放elk目录 mkdir /elk/ mkdir /elk/soft下载 es 、kibana、Logstash、filebeat二进制包 cd /elk/softwget https://art…...

原生微信小程序中封装一个模拟select 下拉框组件
1.首先在components 里面设置组件名称:van-select(随便取名字); 2.新建文件写代码: wxml: <view class"w100 select_all_view"><!-- 标题,可以没有 --><view class…...

商品管理系统引领时尚零售智能化升级 降价商品量锐减30%
根据贝恩咨询公司2024年发布的消费品报告,当前消费品行业正面临增长放缓、全球市场波动及消费者期望变化的巨大压力。为保持市场竞争力,企业需要重新审视其增长战略,重视可持续创新、数字化转型和运营敏捷性。企业必须灵活应对供应链中断和消…...

UE5 5.1.1创建C++项目,显示error C4668和error C4067
因为工作要求,没法使用最新 5.5版本的ue5 而是要用ue5.1和5.2版本。 但是我在安装下载了visual studio2022后,使用 ue5.1编辑器 创建C项目,爆出如下错误。 error C4668: ?????__has_feature?????ΪԤ?????꣬???0????…...
spring boot 集成 redis 实现缓存的完整的例子
Cacheable 注解是 Spring Cache 抽象的一部分,用于声明式地管理缓存。Cacheable 注解本身并不直接指定缓存的存储位置,而是依赖于配置的缓存管理器(CacheManager)来决定缓存数据的存储位置。 常见的缓存存储方式: 1、内存缓存&a…...
json-bigint处理前端精度丢失问题
问题描述:前后端调试过程中,有时候会遇到精度丢失的问题,比如后端给过来的id超过16位,就会出现精度丢失的情况,前端拿到的id与后端给过来的不一致。 解决方案: 1、安装 npm i json-bigint 2、在axios中配置…...

【算法】【优选算法】前缀和(下)
目录 一、560.和为K的⼦数组1.1 前缀和1.2 暴力枚举 二、974.和可被K整除的⼦数组2.1 前缀和2.2 暴力枚举 三、525.连续数组3.1 前缀和3.2 暴力枚举 四、1314.矩阵区域和4.1 前缀和4.2 暴力枚举 一、560.和为K的⼦数组 题目链接:560.和为K的⼦数组 题目描述&#x…...
Node.js 23 发布了!
Node.js 23 现已推出,带来了新功能、性能改进和更好的开发者体验。此次版本提升了兼容性和稳定性,提供了更多工具来构建高效的应用程序。 此外,Node.js 22 将在 10 月 29 日当周被提升为长期支持 (LTS) 版本,进入长期维护阶段&am…...

如何通过低代码逻辑编排实现业务流程自动化?
随着数字化转型的加速,企业对高效、灵活的业务流程自动化需求日益增加。传统开发模式下的定制化解决方案往往周期长、成本高且难以适应快速变化的需求。低代码平台以其直观、简便的操作界面和强大的功能逐渐成为企业实现业务流程自动化的理想选择。本文将探讨低代码…...

thinkphp6模板调用URL方法生成的链接异常
var uul params.url ;console.log(params.url);console.log("{:Url(UserLog/index)}");console.log("{:Url("uul")}"); 生成的链接地址 UserLog/index /jjg/index.php/Home/UserLog/index.html /jjg/index.php/Home/Index/UserLog/index.html…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...
React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?
系列回顾: 在上一篇《React核心概念:State是什么?》中,我们学习了如何使用useState让一个组件拥有自己的内部数据(State),并通过一个计数器案例,实现了组件的自我更新。这很棒&#…...