Qt 之 简单截图功能(二)实现可移动选中区域

Qml Image 截取一部分图片形式 Qml Image 截取一部分 :每次只显示一张图片的一部分,以有不同的状态显示。 阅读详情

一、简述

在 Qt 之 简单截图功能(一)实现鼠标选中区域截图 中我们简单介绍了截图,也实现了简单截图,但是截完图片后不可以继续移动选中区域,这一篇中将讲述在选取完截图区域后可再次用鼠标拖动移动选中区域。

效果图:

这里写图片描述

二、代码之路

—— 完整代码请见文章结尾下载链接。

capturescreen.cpp

#include "capturescreen.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QMouseEvent>

CaptureScreen::CaptureScreen(QWidget *parent)
	: QWidget(parent)
	, m_currentCaptureState(initCapture)
{
	initWindow();
	loadBackgroundPixmap();
}

CaptureScreen::~CaptureScreen()
{

}

void CaptureScreen::initWindow()
{
	this->setMouseTracking(true);
	// 由于存在类似QQ这样界面始终显示在最顶层,设置属性 Qt::WindowStaysOnTopHint;
	this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
	setWindowState(Qt::WindowActive | Qt::WindowFullScreen);
	this->setMouseTracking(true);
}

void CaptureScreen::loadBackgroundPixmap()
{
	m_loadPixmap = QPixmap::grabWindow(QApplication::desktop()->winId()); //抓取当前屏幕的图片;
	m_screenwidth = m_loadPixmap.width();
	m_screenheight = m_loadPixmap.height();
}

void CaptureScreen::mousePressEvent(QMouseEvent *event)
{
	if (event->button() == Qt::LeftButton && m_currentCaptureState == initCapture)
	{
		m_currentCaptureState = beginCaptureImage;
		m_beginPoint = event->pos();
	}
	else if (event->button() == Qt::LeftButton && isPressPointInSelectRect(event->pos()))
	{
		m_currentCaptureState = beginMoveCaptureArea;
		setCursor(Qt::SizeAllCursor);
		m_beginMovePoint = event->pos();
	}

	return QWidget::mousePressEvent(event);
}

void CaptureScreen::mouseMoveEvent(QMouseEvent* event)
{
	if (m_currentCaptureState == beginCaptureImage)
	{
		m_endPoint = event->pos();
		update();
	}
	else if (m_currentCaptureState == beginMoveCaptureArea)
	{
		m_endMovePoint = event->pos();
		update();
	}

	// 根据鼠标是否在选中区域内设置鼠标样式;
	if (isPressPointInSelectRect(event->pos()))
	{
		setCursor(Qt::SizeAllCursor);
	}
	else if (!isPressPointInSelectRect(event->pos()) && m_currentCaptureState != beginMoveCaptureArea)
	{
		setCursor(Qt::ArrowCursor);
	}
	
	return QWidget::mouseMoveEvent(event);
}

void CaptureScreen::mouseReleaseEvent(QMouseEvent *event)
{
	if (m_currentCaptureState == beginCaptureImage)
	{
		m_currentCaptureState = finishCaptureImage;
		m_endPoint = event->pos();
		update();
	}
	else if (m_currentCaptureState == beginMoveCaptureArea)
	{
		m_currentCaptureState = finishMoveCaptureArea;
		m_endMovePoint = event->pos();
		update();
	}
	return QWidget::mouseReleaseEvent(event);
}

// 当前鼠标坐标是否在选取的矩形区域内;
bool CaptureScreen::isPressPointInSelectRect(QPoint mousePressPoint)
{
	QRect selectRect = getRect(m_beginPoint, m_endPoint);
	if (selectRect.contains(mousePressPoint))
	{
		return true;
	}

	return false;
}

void CaptureScreen::paintEvent(QPaintEvent *event)
{
	m_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);           //画影罩效果;

	switch (m_currentCaptureState)
	{
	case initCapture:
		break;
	case beginCaptureImage:
	case finishCaptureImage:
	case beginMoveCaptureArea:
	case finishMoveCaptureArea:
		m_currentSelectRect = getSelectRect();
		drawCaptureImage();
	default:
		break;
	}

	m_painter.end();  //重绘结束;
}

// 根据当前截取状态获取当前选中的截图区域;
QRect CaptureScreen::getSelectRect()
{
	if (m_currentCaptureState == beginCaptureImage || m_currentCaptureState == finishCaptureImage)
	{
		return getRect(m_beginPoint, m_endPoint);
	}
	else if (m_currentCaptureState == beginMoveCaptureArea || m_currentCaptureState == finishMoveCaptureArea)
	{
		return getMoveRect();
	}

	return QRect(0, 0, 0, 0);
}

// 绘制当前选中的截图区域;
void CaptureScreen::drawCaptureImage()
{
	m_capturePixmap = m_loadPixmap.copy(m_currentSelectRect);
	m_painter.drawPixmap(m_currentSelectRect.topLeft(), m_capturePixmap);
	m_painter.drawRect(m_currentSelectRect);
}

void CaptureScreen::keyPressEvent(QKeyEvent *event)
{
	// Esc 键退出截图;
	if (event->key() == Qt::Key_Escape)
	{
		close();
	}
	// Eeter键完成截图;
	if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
	{
		signalCompleteCature(m_capturePixmap);
		close();
	}
}

// 根据beginPoint , endPoint 获取当前选中的矩形
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);
	// 避免宽或高为零时拷贝截图有误;
	// 可以看QQ截图,当选取截图宽或高为零时默认为2;
	if (selectedRect.width() == 0)
	{
		selectedRect.setWidth(1);
	}
	if (selectedRect.height() == 0)
	{
		selectedRect.setHeight(1);
	}

	return selectedRect;
}

// 获取移动后,当前选中的矩形;
QRect CaptureScreen::getMoveRect()
{
	// 通过getMovePoint方法先检查当前是否移动超出屏幕;
	QPoint movePoint = getMovePoint();
	QPoint beginPoint = m_beginPoint + movePoint;
	QPoint endPoint = m_endPoint + movePoint;
	// 结束移动选区时更新当前m_beginPoint , m_endPoint,防止下一次操作时截取的图片有问题;
	if (m_currentCaptureState == finishMoveCaptureArea)
	{
		m_beginPoint = beginPoint;
		m_endPoint = endPoint;
		m_beginMovePoint = QPoint(0, 0);
		m_endMovePoint = QPoint(0, 0);
	}
	return getRect(beginPoint, endPoint);
}

QPoint CaptureScreen::getMovePoint()
{
	QPoint movePoint = m_endMovePoint - m_beginMovePoint;
	QRect currentRect = getRect(m_beginPoint, m_endPoint);
	// 检查当前是否移动超出屏幕;

	//移动选区是否超出屏幕左边界;
	if (currentRect.topLeft().x() + movePoint.x() < 0)
	{
		movePoint.setX(0 - currentRect.topLeft().x());
	}
	//移动选区是否超出屏幕上边界;
	if (currentRect.topLeft().y() + movePoint.y() < 0)
	{
		movePoint.setY(0 - currentRect.topLeft().y());
	}
	//移动选区是否超出屏幕右边界;
	if (currentRect.bottomRight().x() + movePoint.x() > m_screenwidth)
	{
		movePoint.setX(m_screenwidth - currentRect.bottomRight().x());
	}
	//移动选区是否超出屏幕下边界;
	if (currentRect.bottomRight().y() + movePoint.y() > m_screenheight)
	{
		movePoint.setY(m_screenheight - currentRect.bottomRight().y());
	}

	return movePoint;
}

尾

以上在 Qt 之 实现简单截图功能(一) 的基础之上完成了 在选取完截图区域后,能够拖动截图区域选择新的区域,下一篇中将完成可以用鼠标拖动截图区域的各个顶点改变截图区域大小的功能,详情见下图。

欢迎评论,欢迎一起交流。

这里写图片描述

在这里插入图片描述

代码下载

Qt 之 实现简单截图功能(二)

Kali Linux 2026.x 最新版在VMware虚拟机中的完整安装、汉化与配置指南 最近在网络安全学习和渗透测试实践中,很多朋友都卡在了第一步——搭建一个稳定、好用的Kali Linux环境。网上的教程要么版本老旧,要么步骤零散,虚拟机配置、系统激活、中文汉化这些关键环节总是分开讲,跟着操作常常遇到各种报错。本文将为你整合一套从零开始的完整闭环方案,涵盖 Kali Linux 2026.x 最新版 的下载、在VMware虚拟机中的安装、系统基本配置、以及新手最关心的激活与汉化问题。文末还提供了常见问题排查清单,确保你能获得一个开箱即用、功能完整的渗透测试学习环境。无论你是网络安全新手,还是 阅读详情

相关推荐

Qt实现截图(附完整源码)

Qt实现截图(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 997

QT 实现简单截图功能

QT 实现简单截图功能 代码内容完善、有详细的代码注释所以不在赘述。 头文件CaptureScreen.h #ifndef CAPTURESCREEN_H #define CAPTURESCREEN_H #include <QWidget> #include <QPainter> enum CaptureState{ initCapture, beginCaptureImage, finishCaptureImage, beginMoveCaptureArea,

间接性踌躇满志,持续性混吃等死。 813

Qt项目中,实现屏幕截图功能的模块详细实现(可通用)

总第52篇屏幕截图功能,在很多软件中都有使用。本文主要梳理一下这个功能的实现,方便在以后的项目中快速移植,对于这方面不太熟悉的,也可以参考一下其实现方式。程序的实现效果图,见文章末尾。头文件主要包含两个类,一个是截屏对象类,另一个是截屏窗口类,在截屏窗口中调用截屏对象。其详细的变量、方法定义如下:#ifndef SCREENWIDGET_H #define SCREENWIDGET_H #inc...

实战开发者Airex 1681

利用QT实现截屏的四种方法

利用QT实现截屏的四种方法; 一:截取整个屏幕 (1)代码如下: void Test::slotGrabFullScreen() {     QScreen *screen = QGuiApplication::primaryScreen();     QString filePathName = "full-";     filePathName += QDateT

huangqi734044860的专栏 5万+

第二十七章、containers容器类部件QTabWidget选项窗部件详解

老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一、概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有如下: 容器类部件中的TabWidget选项卡组件是一个带一到多个选项卡栏和对应页面区域的组件,对应类QTabWidget,每个选项卡栏对应一个单独的页面,用于显示与每个选项卡相关的内容。默认情...

老猿Python 1575

从BAM到bigWig:用UCSC工具链完成测序数据可视化的完整流程

本文详细介绍了从BAM文件到bigWig格式的基因组数据可视化完整流程,涵盖UCSC工具链配置、文件格式转换、参数优化及常见问题解决方案。通过实战指南帮助研究人员高效完成测序数据可视化,特别适合ChIP-seq和RNA-seq数据分析。

weixin_29309213的博客 707

Qt 之 简单截图功能(三)实现可拖拽选中区域

一、简述在 Qt 之 简单截图功能(一)实现鼠标选中区域截图 、 Qt 之 简单截图功能(二)实现可移动选中区域 中简单叙述了实现截图功能的两小步,今天第三篇来实现可拖拽选中矩形顶点进行重新选择截图区域,话不多说先看效果图,再上代码。效果图:二、代码之路这一篇中将实现实现如何通过鼠标拖拽重新选取截图区域。代码可能稍长,整体代码是在前两篇的基础上完善的,建议先从 Qt 之 简单截图功能(一)实现鼠标选......

前行之路还需前行 1万+

利用netmq在相机应用于unity之间传输图像数据

Unity工业相机接入方案解析 本文探讨了在Unity中接入不同品牌工业相机的技术方案。研究发现: Basler相机可直接调用官方DLL(pylonc.net.dll)实现接入 海康和大恒相机因驱动DLL依赖C++组件,无法直接调用 解决方案:通过独立进程(相机应用程序)与Unity进行通信,采用NetMQ实现图像数据传输 技术实现要点: 相机端:使用PublisherSocket发布JPEG图像帧 Unity端:通过SubscriberSocket订阅图像数据 优化:设置高水位线控制缓存帧数,避免数据堆积

weixin_46450859的博客 417

Qt实现截图(可移动截屏区域并修改大小)

可以显示截图区域大小,可以任意拖动截图区域,四个边框可拖拽修改大小

weixin_46246664的博客 2010

【2023】Java利用modbus4j实现工业设备Modbus TCP数据采集与解析

本文详细介绍了在2023年使用Java和modbus4j库实现工业设备Modbus TCP数据采集与解析的完整实践。内容涵盖开发环境搭建、TCP连接建立、开关量与模拟量数据的读取与解析、批量读取性能优化、控制指令写入以及常见错误排查指南,为开发者构建稳定高效的工业物联网数据采集系统提供全面指导。

rose2的博客 723

保姆级教程:用ROS2 Humble和激光雷达,5分钟搞定机器人避障(附Python代码)

本文提供了一份详细的ROS2 Humble激光雷达避障实战指南,帮助开发者快速实现机器人避障功能。通过环境配置、硬件连接和Python代码实现,5分钟内即可让机器人自主避开障碍物。文章还涵盖了参数调优、常见问题排查及进阶优化技巧,适合机器人开发初学者和进阶用户。

weixin_42528902的博客 342

Qt实现微信截图功能(一)

使用Qt实现微信截图部分功能,Qt虽然不是无所不能,但是我们可以尽其所能。

前行之路还需前行 3032

用STM32F407做个USB声卡:从CubeMX配置到播放录音全功能实战(附源码)

本文详细介绍了如何使用STM32F407开发板实现USB音频设备的全功能实战,包括CubeMX配置、硬件连接、音频流处理和性能优化。通过双缓冲DMA机制和音频数据处理流程,开发者可以构建高质量的USB声卡系统,适用于录音和播放场景。附源码,助力快速上手STM32音频开发。

weixin_30301449的博客 516

Qt 实现高仿微信的滑动截屏工具(二:新增可拖拽截图框与位置显示)

截图后可移动矩形:通过和实现。当前截图位置显示:通过和实现。截图 Icon 设计:通过setMyStyle为按钮设置图标和样式。源码已经给小伙伴们整理好了,微信搜索 嵌入式工程之家 关注公众号回复 截图 即可获得源码和详细操作指示哦~

LKHzzzzz的博客 495

【IIC通信】Chap.1(I2C)IIC通信原理、IIC读写时序详解

IIC通信以两根连线SDA、SCL实现了完善的全双工同步数据传送, 可以方便地构成多机系统和外围器件扩展系统。

Jie_MSD的博客 2万+

MIPI D-PHY IP 使用说明(一)

目录 前言 一、IP 特点 二、IP 可用性 三、IP 总览 四、IP 声明 五、IP 结构 六、IP 分流桥 模式 七、端口描述 1、PPI 接口信号 1、常规 PPI控制信号 2、发送模式 时钟通道 高速 PPI 信号 3、发送模式 时钟通道 逃逸模式PPI 信号 4、发送模式 数据通道 高速 PPI 信号 5、发送模式 数据通道 控制接口PPI 信号 6、发送模式 ...

记录所学,分享知识,结识挚友 2504

Qt5.15 仿QQ截图

基于Qt5.15的仿QQ截图前言一、包括的功能内容——细分二、分析QQ截图基本原理思路三、效果图,有图有真相:目前功能结语截图工具源码:欢迎大家在此互相交流以下是两个Qt编写的小工具: 前言 学习进度所迫,目前想基于Qt开发一个类似于QQ截图工具的软件,以及后期做一些扩展功能的准备。 一、包括的功能内容——细分 无框半透明工具界面的绘制(任务栏不出现应用图标显示) 可拉伸框体区域的绘制(截图区域,也可以用控件) 放大镜效果,放大局部区域(放大鼠标所在位置的细节) 颜色拾取器,拾取鼠标所在位置像素的R

世界和平 564

【从零开始学习 UVM】1.1、UVM 概述 —— Preface

【从零开始学习 UVM】1.1、UVM 概述 —— Preface

努力,加油每一天鸭~ 826

如何用Qt实现头像剪辑窗口---手把手系列

因此我们这里要做一个区分,把QWidget中显示图片的label分成正在被裁剪窗口选中的矩形区域和未被选中的矩形区域,其中,被选中的矩形区域,因为需要它随着鼠标的拖动而去移动,所以它也是一个自定义部件。m_cutDialog是裁剪矩形,也就是一个高亮部分的矩形,这个矩形当然也可以用QWidget去实现,但是需要重写mousePressEvent函数,使它能跟着鼠标拖动,并且设置好它的初始坐标和在整个图片中的初始位置。整个窗口分两部分,一部分是用来显示一张完整的图片,另一个小窗口用来获取目前准备裁剪的图片。

m0_61167558的博客 466

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Qt6-网络关机助手(开机自启版)实现

在前面已经预告了,要写一个网络关机助手了。这里先看下我的成果吧。 源码连接:https://download.youkuaiyun.com/download/z609932088/15422254 程序截图如下 目前这个小工具已经开发完成,欢迎小伙伴们一起交流。 设置程序图标 Qt6这里设置程序运行的图标又回到了以前的版本了。首先在工程文件夹下面建立一个rc文件,输入以下内容 IDI_ICON1 ICON DISCARDABLE "icon.ico

DreamLife&Yaothos 1311

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

QT(12):QGraphicsView

还可以通过创建 QGraphicsView 的子类并重新实现鼠标和键事件处理程序来提供自己的自定义场景交互。为了简化以编程方式与视图中的项交互的方式,QGraphicsView 提供了映射函数mapToScene()和mapFromScene(),以及item访问器items()和itemAt()。这些函数允许在视图坐标和场景坐标之间映射点、矩形、多边形和路径,并使用视图坐标查找场景中的item。

qq_45088122的博客 1487

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Qt6 multimedia开发一个摄像头录像机

Qt 6 附加模块multimedia可用于多媒体的开发,今天使用它可以快速开发一个摄像头录像机。毕业季用作本科毕业设计软件应该可以的。

noevil的博客 1538

ksnip常见问题解决方案:从安装到使用的完整排错指南

Ksnip是一款功能强大的跨平台截图和标注工具,支持Linux、Windows和macOS系统。无论您是新手用户还是资深开发者,在使用ksnip过程中都可能遇到各种问题。本指南将为您提供从安装到使用过程中常见问题的完整解决方案,帮助您快速解决遇到的困难。🚀 ## 安装问题排查 ### 1. 无法找到ksnip安装包 如果您在Linux系统上无法找到ksnip的安装包,可以尝试以下方法:

gitblog_00421的博客 1076

【qt】GraphicsView绘图架构

主要是知道视图,场景,图形项三者的关系,还有三者不同的坐标系,视图是在左上角是原点,场景和图形项都是自定义的.还有就是用这些的优点,可交互等等…加油!

qq_74047911的博客 2042

第15.33节 PyQt(Python+Qt)入门学习:containers容器类部件QTabWidget选项窗部件简介

老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一、概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有如下: 容器类部件中的TabWidget选项卡组件是一个带一到多个选项卡栏和对应页面区域的组件,对应类QTabWidget,每个选项卡栏对应一个单独的页面,用于显示与每个选项卡相关的内容。默认情...

老猿Python 2585

Flameshot 11.0 深度解析:CLI 架构重构、一次性截屏模式与全新命令行能力

本指南基于 Flameshot 官方 V11.0 Beta 发布说明([docs/ReleaseNotes_11.0.md](https://link.gitcode.com/i/cd37b9b3cb0976ed30198097a2ed9335)),系统梳理该版本对截图工具内部架构的里程碑式改造:CLI 全面重构并摆脱对 DBus 的依赖、新增「one-off 一次性模式」使后台托盘组件变为可选、

gitblog_00271的博客 75
上一篇: Qt 之 简单截图功能(一)实现鼠标选中区域截图
下一篇: Qt 之 简单截图功能(三)实现可拖拽选中区域
前行中的小猪
前行中的小猪 领域专家: C/C++技术领域 领域专家: C/C++技术领域
博客等级 码龄10年 4万+粉丝 134原创
评论 14
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值