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

Qt 完成图片的缩放拖动

1. 事件和函数

主要使用事件paintEvent(QPaintEvent *event)和drawTiledPixmap函数实现绘图。

  1. paintEvent事件在改变窗口大小、移动窗口、手动调用update等情形下会被调用。
  2. 需先了解下绘图该函数的用法。 - QPainter::drawTiledPixmap(int x, int y, int w, int h, const QPixmap &pm, int sx, int sy)
  3. 效果:

2. 建立项目

假设已新建了mainwindow项目。现再添加一界面用于单独显示图片,作为子窗口供调用(当然,也可在main.c直接调用,作为父窗口)。
1)右击界面文件—添加新文件—QT—QT设计师界面类—choose—Dialog without buttons。类名为CImgPaint。
打开ui文件,添加控件,主要是label和button,

具体属性列表如下:

其中,label控件仅仅是提供绘图的区域,但最终绘图不是绘在label控件上。

3. 头文件添加变量,编写构造函数

头文件中包含头文件

#define USE_OPENCV 0#include <QDialog>
#include "mainwindow.h"
#include "QPoint"
using namespace std;
#if USE_OPENCV#include "opencv2/opencv.hpp"#include <opencv2/core.hpp>using namespace cv;
#endifnamespace Ui {
class CImgPaint;
}
类中添加成员变量
private:QPixmap  pix_src,pix_fix;//原始图片及缩放图片float ratio=1.0;        //缩放比QRect paint_rect;           //绘画限制区域int paint_xe,paint_ye,paint_we,paint_he;//期望绘画区域int paint_x,paint_y,paint_w,paint_h;//实际绘画区域int pix_sx,pix_sy;          //选择图片的起始x、y开始绘画int step_val = 20;          //单次移动步长bool mouse_press_flag = false;//鼠标是否按下QPoint mouse_pos_pre,mouse_pos_cur;//记录鼠标位置

 构造函数中,添加输入图片的读取,以及变量初始化。

#include "CImgPaint.h"
#include "ui_cimgpaint.h"
#include "QDebug"
#include "QPainter"
#include "QWheelEvent"
#include "QImage"
CImgPaint::CImgPaint(QWidget *parent) :QDialog(parent),ui(new Ui::CImgPaint)
{ui->setupUi(this);#if USE_OPENCVcv::Mat img = cv::imread("lenaGray.jpg",-1);pix_src = get_pixmap_from_mat(img);
#elseQImage qimg ;qimg.load("./lenaGray.jpg");pix_src = pix_src.fromImage(qimg);
#endifpaint_rect.setRect(ui->label_paint->x()+1,ui->label_paint->y()+1,ui->label_paint->width()+1,ui->label_paint->height()+1);pix_fix = pix_src.scaled(paint_rect.width(),paint_rect.height(),Qt::KeepAspectRatio,Qt::FastTransformation);reset_para();update_para();
}void CImgPaint::reset_para(void)
{ratio = 1.0;paint_xe = paint_x =paint_rect.x()  ;paint_ye = paint_y = paint_rect.y();paint_we = paint_w = paint_rect.width();paint_he = paint_h = paint_rect.height();pix_sx = 0;pix_sy = 0;
}#if USE_OPENCV
QPixmap CImgPaint::get_pixmap_from_mat(Mat img)
{cv::Mat img_temp = img.clone();QImage::Format format = QImage::Format_RGB888;if(img_temp.channels()==1){format  = QImage::Format_Grayscale8;}if(img_temp.channels()==3){cv::cvtColor(img_temp,img_temp,CV_BGR2RGB);//opencv 按BGR处理}if(img_temp.depth()==CV_16U){img_temp.convertTo(img_temp,CV_8U,1.0/257.0);}QPixmap pixmap = QPixmap::fromImage(QImage(img_temp.data,img_temp.cols,img_temp.rows,(int)img_temp.step,format));return pixmap;}
#endif
CImgPaint::~CImgPaint()
{delete ui;
}

update_para函数用来确定drawTiledPixmap函数的各参数。

void CImgPaint::update_para(void)
{//*************** 0. 处理放大和缩小 **********************//// 放大缩小仅仅改变width和height,图像的起始点,不变int w,h;w = ratio*paint_rect.width();//放大或缩小,统一对标到画布尺寸h = ratio*paint_rect.height();pix_fix = pix_src.scaled(w,h,Qt::KeepAspectRatio,Qt::FastTransformation);//对输入的原图进行放大、缩小paint_we = pix_fix.width();//得到初始的图像w、h期望值paint_he = pix_fix.height();//*************** 1. 处理Y方向 **********************////1.1 首先确定实际绘图的起点,绘图的起点应在画布的大小范围内 //// 若期望的起点超出画布上限,则设置截取图像的起始位置sypaint_y = paint_ye;if(paint_y < paint_rect.y()){pix_sy =  paint_rect.y() - paint_y;pix_sy = pix_sy>pix_fix.height()?pix_fix.height():pix_sy;paint_y = paint_rect.y();}else{pix_sy = 0;}//若期望的起点超出画布下限,不允许if(paint_y>=(paint_rect.y()+paint_rect.height()-1)){paint_y = (paint_rect.y()+paint_rect.height()-1);}//1.2 再确定终点,即高度//对于图片本身,减去sy,得到图片本身剩余的高度paint_he -= pix_sy;// 图片本身的高度,同样不可超过画图区域剩余的高度paint_he = paint_he>( paint_rect.height()+paint_rect.y()-paint_y )?(paint_rect.height()+paint_rect.y()-paint_y):paint_he;//*************** 2. 处理X方向 **********************////1.1 首先确定实际绘图的起点,绘图的起点应在画布的大小范围内 //// 若期望的起点超出画布上限,则设置截取图像的起始位置sxpaint_x = paint_xe;if(paint_x < paint_rect.x()){pix_sx =  paint_rect.x() - paint_x;pix_sx = pix_sx>pix_fix.width()?pix_fix.width():pix_sx;paint_x = paint_rect.x();}else{pix_sx = 0;}//若期望的起点超出画布下限,不允许if(paint_x>=(paint_rect.x()+paint_rect.width()-1)){paint_x = (paint_rect.x()+paint_rect.width()-1);}//1.2 再确定终点,即宽度//对于图片本身,减去sx,得到图片本身剩余的宽度paint_we -= pix_sx;// 图片本身的宽度,同样不可超过画图区域剩余的宽度paint_we = paint_we>( paint_rect.width()+paint_rect.x()-paint_x )?(paint_rect.width()+paint_rect.x()-paint_x):paint_we;paint_h = paint_he;paint_w = paint_we;qDebug()<<paint_rect;qDebug()<<paint_x<<paint_y<<paint_w<<paint_h<<pix_fix<<pix_sx<<pix_sy;}

4. paintEvent事件

头文件声明void paintEvent(QPaintEvent *event);并且在cpp文件中重写该事件函数


public slots:void paintEvent(QPaintEvent *event);
void CImgPaint::paintEvent(QPaintEvent *event)
{QPainter painter(this);painter.setRenderHints(QPainter::SmoothPixmapTransform|QPainter::Antialiasing|QPainter::TextAntialiasing);painter.drawRect(paint_rect.x()-1,paint_rect.y()-1,paint_rect.width()+1,paint_rect.height()+1); //画框painter.drawTiledPixmap(paint_x,paint_y,paint_w,paint_h,pix_fix,pix_sx,pix_sy);//绘图}

 5. 编写按钮的回调函数

按钮的回调函数主要用来修改变量的值。修改完后,调用update_para、update,重绘。
update_para函数用来确定drawTiledPixmap函数的各参数。

void CImgPaint::on_pushButton_zoomIn_clicked()
{ratio = ratio + 0.1*ratio;update_para();this->update();
}void CImgPaint::on_pushButton_zoomOut_clicked()
{ratio = ratio - 0.1*ratio;update_para();this->update();
}void CImgPaint::on_pushButton_Up_clicked()
{paint_ye -=step_val;update_para();this->update();
}void CImgPaint::on_pushButton_Down_clicked()
{paint_ye +=step_val;update_para();this->update();}void CImgPaint::on_pushButton_Left_clicked()
{paint_xe -= step_val;update_para();this->update();}void CImgPaint::on_pushButton_Right_clicked()
{paint_xe += step_val;update_para();this->update();}void CImgPaint::on_pushButton_reset_clicked()
{reset_para();update_para();this->update();
}

这样,可以通过点击按钮来完成图片的移动、缩放。

6.鼠标拖动、滚轮实现图片拖动及缩放

重写如下虚函数

public slots:void wheelEvent(QWheelEvent *event);bool event(QEvent *event);void mouseDoubleClickEvent(QMouseEvent *event);
void CImgPaint::mouseDoubleClickEvent(QMouseEvent *event)
{if(event->button()==Qt::LeftButton && paint_rect.contains(event->pos())){reset_para();update_para();this->update();}
}
bool CImgPaint::event(QEvent *event)
{qDebug()<<"event";if(event->type() == QEvent::MouseButtonPress ){QMouseEvent *mouse = dynamic_cast<QMouseEvent* >(event);//QPoint temp = mouse->pos();if(mouse->button()==Qt::LeftButton && paint_rect.contains(mouse->pos())){mouse_press_flag = true;QApplication::setOverrideCursor(Qt::OpenHandCursor);mouse_pos_pre = mouse->pos();}qDebug()<<"MouseButtonPress";}else if(event->type() == QEvent::MouseButtonRelease){QMouseEvent *mouse = dynamic_cast<QMouseEvent* >(event);//判断鼠标是否是左键释放,且之前是在绘画区域if(mouse->button()==Qt::LeftButton && mouse_press_flag ){QApplication::setOverrideCursor(Qt::ArrowCursor); //改回鼠标样式mouse_press_flag=false;}qDebug()<<"MouseButtonRelease";}if(event->type() == QEvent::MouseMove)              //移动图片{if(mouse_press_flag){QMouseEvent *mouse = dynamic_cast<QMouseEvent* >(event);mouse_pos_cur = mouse->pos();int dx = mouse_pos_cur.x() - mouse_pos_pre.x();int dy = mouse_pos_cur.y() - mouse_pos_pre.y();mouse_pos_pre = mouse_pos_cur;paint_xe += dx;paint_ye += dy;update_para();this->update();}qDebug()<<"MouseMove";}return QWidget::event(event);
}void CImgPaint::wheelEvent(QWheelEvent *event)
{if (event->delta()>0) //上滑,缩小{on_pushButton_zoomIn_clicked();}else //下滑,放大{on_pushButton_zoomOut_clicked();}event->accept();
}

可实现鼠标拖动、滚轮的方式来完成图片的拖动、缩放。
源码下载地址(附使用方法):
https://download.csdn.net/download/xiaohuolong1827/78238541

原链接

相关文章:

Qt 完成图片的缩放拖动

1. 事件和函数 主要使用事件paintEvent(QPaintEvent *event)和drawTiledPixmap函数实现绘图。 paintEvent事件在改变窗口大小、移动窗口、手动调用update等情形下会被调用。需先了解下绘图该函数的用法。 - QPainter::drawTiledPixmap(int x, int y, int w, int h, const QPi…...

Linux 内核工具 iptables 配置TCP/UDP端口转发(命令参考)

1、配置TCP端口转发 把本机20000/TCP端口转发到7.7.7.7:20000 iptables -t nat -A PREROUTING -p tcp --dport 20000 -j DNAT --to-destination 7.7.7.7:20000 iptables -t nat -A POSTROUTING -j MASQUERADE 2、配置UDP端口转发 把本机20000/UDP端口转发到7.7.7.7:20000 i…...

love 2d Lua 俄罗斯方块超详细教程

源码已经更新在CSDN的码库里&#xff1a; git clone https://gitcode.com/funsion/love2d-game.git 一直在找Lua 能快速便捷实现图形界面的软件&#xff0c;找了一堆&#xff0c;终于发现love2d是小而美的原生lua图形界面实现的方式。 并参考相关教程做了一个更详细的&#x…...

SpringBoot+ElasticSearch实现文档内容抽取、高亮分词、全文检索

需求 产品希望我们这边能够实现用户上传PDF、WORD、TXT之内得文本内容&#xff0c;然后用户可以根据附件名称或文件内容模糊查询文件信息&#xff0c;并可以在线查看文件内容。 一、环境 项目开发环境&#xff1a; 后台管理系统springbootmybatis_plusmysqles 搜索引擎&#…...

利用Redis实现简单的短信登录

在现代应用中&#xff0c;短信登录是一种常见的用户认证方式。它提供了一种便捷的登录方式&#xff0c;同时也增加了账户的安全性。在本文中&#xff0c;我们将介绍如何使用 Redis 实现短信登录的功能&#xff0c;并提供相应的 Java 实现层代码。 1、短信验证码的生成与存储当用…...

在 Linux 中通过 SSH 执行远程命令时,无法自动加载环境变量(已解决)

问题场景 目前我的环境变量都存储在 /etc/profile 文件中&#xff0c;当我通过远程 SSH 执行一些命令时&#xff0c;提示命令找不到&#xff0c;如下所示&#xff1a; 问题出现原因 这里找到了一张出自尚硅谷的图片&#xff0c;很好的解释了该问题&#xff1a; 这是由于 Linu…...

c++使用类的一些注意事项

前言&#xff1a; 本篇内容为前面的补充&#xff0c;介绍了我们使用类时需要注意些什么以及一些编译器的优化&#xff0c;可能有些理解不到位或者错误&#xff0c;请斧正。 目录 前言&#xff1a; 1.再谈构造函数 2.&#xff08;c98&#xff09;隐式类型转换中的编译器的优…...

C++蓝桥考级一级到十八级的考点内容整理

以下是C蓝桥考级一级到十八级的考点内容整理&#xff1a; C一级考点内容 C程序基本结构 初步了解C编程了解C程序基本结构&#xff1a;头文件、命名空间、主函数、基本输入输出 cin、cout C二级考点内容 数据类型与变量 掌握编程中数学表达式的计算方式基础数据类型、变量的…...

C++智能指针简单剖析

导读 最近在补看《C Primer Plus》第六版&#xff0c;这的确是本好书&#xff0c;其中关于智能指针的章节解析的非常清晰&#xff0c;一解我以前的多处困惑。C面试过程中&#xff0c;很多面试官都喜欢问智能指针相关的问题&#xff0c;比如你知道哪些智能指针&#xff1f;shar…...

mysql笔记:25. docker环境中mysql主从复制、主主复制实操

文章目录 一、准备工作1. 安装配置Docker2. 准备MySQL相关的配置和数据目录 二、基于日志点的主从复制1. 配置Master服务器1.1 修改配置文件1.2. 在docker中启动Master节点1.3. 创建用户并授权 2. 配置Slave1服务器2.1. 修改配置2.2. 启动服务2.3. 指定Master2.4. 开始复制 3. …...

大数据面试专题 -- kafka

1、什么是消息队列&#xff1f; 是一个用于存放数据的组件&#xff0c;用于系统之间或者是模块之间的消息传递。 2、消息队列的应用场景&#xff1f; 主要是用于模块之间的解耦合、异步处理、日志处理、流量削峰 3、什么是kafka&#xff1f; kafka是一种基于订阅发布模式的…...

深度学习入门简单实现一个神经网络

实现一个三层神经网络 引言测试数据 代码 引言 今天我们实现一个简单的神经网络 俩个输入神经元 隐藏层两个神经元 一个输出神经元 激活函数我们使用sigmoid 优化方法使用梯度下降 我们前期准备是需要把这些神经元的关系理清楚 x1&#xff1a;第一个输入 x2&#xff1a;第二个…...

win11 环境配置 之 Jmeter(JDK17版本)

一、安装 JDK 1. 安装 jdk 截至当前最新时间&#xff1a; 2024.3.27 jdk最新的版本 是 官网下载地址&#xff1a; https://www.oracle.com/java/technologies/downloads/ 建议下载 jdk17 另存为到该电脑的 D 盘下&#xff0c;新建jdk文件夹 开始安装到 jdk 文件夹下 2. 配…...

Windows下载使用nc(netcat)命令

‘nc’ 不是内部或外部命令&#xff0c;也不是可运行的程序&#xff1f; 点击链接地址&#xff0c;下载压缩包。 完成后解压 使用方式&#xff08;三种&#xff09;&#xff1a; 1、直接双击exe使用 2、把这个exe放到cmd启动的默认路径下 放到默认路径下&#xff0c;使用nc&a…...

istio 设置 istio-proxy sidecar 的 resource 的 limit 和 request

方式一 修改 configmap 查看当前 sidecar 的 cpu 和 memory 的配额 在 istio-sidecar-injector 中查找&#xff0c;修改后重启 pod 可以生效&#xff08;下面那个 proxy_init 配置不管&#xff0c;不知道是干嘛的&#xff09; 方式二 如果是通过 iop 安装的 istio&#xf…...

flutter弹框

alertDialog:弹框 simpleDialog:选择弹框 showModalBottomSheet:底部弹出弹框 showtoast:三方插件弹框 Navigator.of(context).pop(点击取消) 关闭弹框,传递参数 import package:flutter/material.dart; // import package:flutter/cupertino.dart; import package:flut…...

2013年认证杯SPSSPRO杯数学建模B题(第一阶段)流行音乐发展简史全过程文档及程序

2013年认证杯SPSSPRO杯数学建模 B题 流行音乐发展简史 原题再现&#xff1a; 随着互联网的发展&#xff0c;流行音乐的主要传播媒介从传统的电台和唱片逐渐过渡到网络下载和网络电台等。网络电台需要根据收听者的已知喜好&#xff0c;自动推荐并播放其它音乐。由于每个人喜好…...

代码随想录算法训练营第39天 | 62.不同路径, 63不同路径II

Leetcode - 62&#xff1a;不同路径 题目&#xff1a; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#…...

Redis 的慢日志

Redis 的慢日志 Redis 的慢日志&#xff08;Slow Log&#xff09;是用于记录执行时间超过预设阈值的命令请求的系统。慢日志可以帮助运维人员和开发人员识别潜在的性能瓶颈&#xff0c;定位那些可能导致 Redis 性能下降或响应延迟的慢查询。以下是 Redis 慢日志的相关细节&…...

第十四届蓝桥杯第十题:蜗牛分享

问题描述 输入格式 输出格式 输出共一行&#xff0c;一个浮点数表示答案&#xff08;四舍五入保留两位小数&#xff09;。 样例输入 3 1 10 11 1 1 2 1样例输出 4.20样例说明 蜗牛路线&#xff1a;(0,0)→(1,0)→(1,1)→(10,1)→(10,0)→(11,0)(0,0)→(1,0)→(1,1)→(10,1…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...