vs2019+Qt实现打开影像并以鼠标为中心用滚轮控制图片缩放

之前写了一个博客讲怎么显示一张影像,那个是基于Qpainter的
今天使用QLabel来显示影像,并且用鼠标滚轮控制缩放。
关于图像的打开和显示,主要参考这个博客
关于如何使图片自适应窗口与铺满窗口,可以参考这个博客。
这两个博客出自同一作者,都很详细。
其中按照第二个博客运行后存在的问题是,点了铺满窗口后,再点自适应窗口,图片没有反应。
解决方法:
1.在头文件添加成员变量

    QImage m_image;

2.在InitImage()函数和File_open()两个中将img拷贝到m_image中,即在这两个函数中都添加:

    m_image = img->copy();

3.在fullSize()和autoSize()两个函数中最前面添加

imgLabel->setPixmap(QPixmap::fromImage(m_image));
imgLabel->resize(m_image.width(), m_image.height());

这样每次点击这俩按钮的时候,label的大小都会回到原影像的大小。

接着这个博客,下面主要讲一下如何用鼠标滚轮控制图片缩放。

1.此时打开较大的影像,鼠标滚轮是控制图片上下移动的。因此首先重写 QAbstractScrollArea 类的wheelEvent函数,让它什么都不要做

void QAbstractScrollArea::wheelEvent(QWheelEvent* event)
{return;
}

2.然后实现滚轮控制label放大缩小

void tstQt::wheelEvent(QWheelEvent* event)
{double ratio = (double)m_image.height() / (double)m_image.width();//图像的比例QPoint numDegrees;                                     // 定义指针类型参数numDegrees用于获取滚轮转角numDegrees = event->angleDelta();                      // 获取滚轮转角int step = 0;                                          // 设置中间参数step用于将获取的数值转换成整数型if (!numDegrees.isNull())                              // 判断滚轮是否转动{step = numDegrees.y();                             // 将滚轮转动数值传给中间参数step}event->accept();                                       // 获取事件int currentWidth = imgLabel->width();                  // 获取当前图像的宽int currentHeight = imgLabel->height();               // 获取当前图像的高currentWidth += step;                                  // 对当前图像的高累加currentHeight += (int)(step*ratio);                                 // 对当前图像的宽累加if (step > 0)                                          // 判断图像是放大还是缩小{QString imgsize = QString("图像放大,尺寸为:%1 * %2").arg(currentWidth).arg(currentHeight);qDebug() << imgsize;                               // 打印放大后的图像尺寸}else{QString imgsize = QString("图像缩小,尺寸为:%1 * %2").arg(currentWidth).arg(currentHeight);qDebug() << imgsize;                                // 打印缩小后的图像尺寸}imgLabel->resize(currentWidth, currentHeight);          // 通过更新图像显示控件的大小来更新图像大小
}

这里设置了一个图像比例因子ratio,可以使图像缩放过程中,比例不要失调。
但是如果先点击了铺满窗口在进行缩放,那label的大小就会变成窗口大小,图像比例就会失调。

但是这时候会发现缩放是以label的左上角为原点进行缩放的,但常用的是以鼠标为中心进行缩放,所以下面实现此部分

1.首先在wheelEvent函数最前面添加代码

 int dockWin_pos = scrollArea->geometry().y()+dock_Image->geometry().y();QScrollBar* tmph = scrollArea->horizontalScrollBar();QScrollBar* tmpv = scrollArea->verticalScrollBar();QPoint pos = event->pos();//得到当前鼠标在窗口的位置QRect tmplab = imgLabel->geometry();//获得imglabel的位置int th = pos.x() - tmplab.x();   // 缩放前鼠标点在label中的坐标int tv = pos.y() - tmplab.y() - dockWin_pos;

这里需要注意的是鼠标位置pos的坐标,它的坐标原点并不是显示图像的区域的左上角,而是。。。不说了,看图

所以我自己量了一下图中两个坐标原点的y轴相差大约79,在上面代码中用dockWin_pos来表示。因为这个坐标原点一开始我没整明白,导致我浪费了一天时间找bug…
2.计算label的放缩比例,因为前面代码是直接加减了一个step,现在计算一下放缩比例就是step/currentwidth
这一句要加在currentWidth变化前。

 double r = (double)(step) / (double)(currentWidth);  //   放缩比例

3.计算滚轮变化量

    int move_x = r * th;int move_y = r * tv;tmph->setValue(tmph->value()+ move_x);tmpv->setValue(tmpv->value() + move_y)

关于整个的原理,得自己画图理解一下了

最后放一下完整的weelEvent()函数代码:

void tstQt::wheelEvent(QWheelEvent* event)
{int dockWin_pos = scrollArea->geometry().y()+dock_Image->geometry().y();QScrollBar* tmph = scrollArea->horizontalScrollBar();QScrollBar* tmpv = scrollArea->verticalScrollBar();QPoint pos = event->pos();//得到当前鼠标在窗口的位置QRect tmplab = imgLabel->geometry();//获得imglabel的位置int th = pos.x() - tmplab.x();int tv = pos.y() - tmplab.y() - dockWin_pos;//缩放前鼠标点在label中的坐标,这里的dockWin_pos是窗体标题的高度imgLabel->setPixmap(QPixmap::fromImage(m_image));      // 显示图像double ratio = (double)m_image.height() / (double)m_image.width();//图像的比例QPoint numDegrees;                                     // 定义指针类型参数numDegrees用于获取滚轮转角numDegrees = event->angleDelta();                      // 获取滚轮转角int step = 0;                                          // 设置中间参数step用于将获取的数值转换成整数型if (!numDegrees.isNull())                              // 判断滚轮是否转动{step = numDegrees.y();                             // 将滚轮转动数值传给中间参数step}event->accept();                                       // 获取事件int currentWidth = imgLabel->width();                  // 获取当前图像的宽int currentHeight = imgLabel->height();                // 获取当前图像的高double r = (double)(step) / (double)(currentWidth);  //   放缩比例currentWidth += step;                                  // 对当前图像的高累加currentHeight += (int)(step*ratio);                    // 对当前图像的宽累加if (step > 0)                                          // 判断图像是放大还是缩小{QString imgsize = QString("图像放大,尺寸为:%1 * %2").arg(currentWidth).arg(currentHeight);qDebug() << imgsize;                               // 打印放大后的图像尺寸}else{QString imgsize = QString("图像缩小,尺寸为:%1 * %2").arg(currentWidth).arg(currentHeight);qDebug() << imgsize;                                // 打印缩小后的图像尺寸}imgLabel->resize(currentWidth, currentHeight);          // 通过更新图像显示控件的大小来更新图像大小int move_x = r * th;int move_y = r * tv;tmph->setValue(tmph->value()+ move_x);tmpv->setValue(tmpv->value() + move_y);
}

QT学习笔记(三)——vs2019+Qt实现打开影像并以鼠标为中心用滚轮控制图片缩放相关推荐

  1. 【QT学习笔记】基于QT的天气预报

    [QT学习笔记]基于QT的天气预报 前言 那就开始吧! 先看一下效果 颜面最重要,画个UI 构造实现 怎么开始? 开始解析数据 关于城市切换 ok 最后源码献上 感谢 前言 学习qt已经有一段时间了, ...

  2. QT学习笔记14(Qt模型视图结构)

    一.基础知识 1.MVC设计模式:是一种与用户界面相关的设计模式,通过此模式,可以有效的分离数据和用户界面. MVC包括三个要素: 表示数据的模型(Model):应用程序的对象 表示用户界面的视图(V ...

  3. QT学习笔记(摘抄)

    QT学习笔记-1.QT主要的对象 说来惭愧学习c++很长时间了一直没有使用c++开发过软件界面 所以现在想认认真真的学习一个c++图形界面框架库 本来想学习Xwidget但是这个资料不大好找 有啥问题 ...

  4. QT学习笔记(三):Qt软件打包发布(QT5.8 _msvc2013_64+Win10_64)

    QT学习笔记(三):Qt软件打包发布(QT5.8 _msvc2013_64+Win10_64) 1.编译方式介绍: 2.动态编译方式打包发布QT程序: 方法一:手动复制 方法二:使用工具 问题& ...

  5. Qt学习笔记之MySQL数据库

    一.MySQL概述 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品.MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQ ...

  6. QT学习笔记(六):Qt5主窗口框架示例

    QT学习笔记(五):Qt5主窗口框架代码示例 一.添加编辑菜单:并在下拉菜单和工具栏中添加"打开文件"动作菜单 #include <QToolButton> #incl ...

  7. QT 学习笔记(六)

    文章目录 一.设计器的使用 二.常用控件 1. Containers 容器类 2. Input Widgets 输出控件 3. Display Widgets 显示类控件 三.代码和运行结果 1. 主 ...

  8. Qt学习笔记,Qt国际化

    Qt学习笔记,Qt国际化 Qt国际化步骤: 第一步:设置.pro文件,加入TRANSLATIONS为国际化做准备 TRANSLATIONS = language/language_en.ts\     ...

  9. Qt学习笔记之数据库

    一.数据库简介 1.1.数据和数据库(DB) 用计算机进行数据处理,首先就要把信息以数据形式存储到计算机中,故数据是可以被计算机接受和处理的符号.根据所表示的信息特征不同,数据有不同的类别,如数字.文 ...

最新文章

  1. 从Preact了解一个类React的框架是怎么实现的(一): 元素创建
  2. electron 剪贴板 截图_用electron开发了一个屏幕截图工具
  3. python程序编译成exe格式
  4. VS2013开发Windows服务项目
  5. 【Java程序设计】多线程基础
  6. apache-cxf测试webservice添加header信息
  7. Layui富文本编辑器提交表单时获取内容为空
  8. 【perl脚本】单行循环正则匹配
  9. Handler机制原理----全解
  10. CASH软件分析差异性可变剪接
  11. sqlite3:sqlite3_column 函数
  12. 什么是工作流开源框架?可提高办公效率吗?
  13. ArcGIS Pro 简介(二)
  14. JAVAEE 实训日志01_20200704 上
  15. 卸载Photoshop
  16. 程序员脱发?看看各个创始人的发量?
  17. 控件用法-WdatePicker 隐藏各按钮
  18. 选择那个汇编编译器,和如何编译16位dos和32位汇编程序。
  19. 老铁们!推荐两款效率神器,一用就舍不得丢了
  20. beyond-谁伴我闯荡-国语谐音

热门文章

  1. 怎样在xp下用上雅黑字体
  2. 用OpenCV实现Photoshop算法(四): 色阶调整
  3. typescript:never与keyof的妙用
  4. HP 3PAR 8440硬盘更换
  5. 直接将ppt转换成word格式的方法
  6. 戴尔服务器R730XD增加万兆光卡后风扇满速运转解决办法
  7. 编程论语 EPIGRAMS IN PROGRAMMING
  8. 手机端小视频(抖音、快手、火山小视频)的视频下载分析
  9. 鱼鹰软件携手31会议为MICE企业提供从内到外的IT解决方案
  10. Expected ']' Expected expression