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.计算滚轮变化量文章来源:https://www.toymoban.com/news/detail-494715.html
int move_x = r * th;
int move_y = r * tv;
tmph->setValue(tmph->value()+ move_x);
tmpv->setValue(tmpv->value() + move_y)
关于整个的原理,得自己画图理解一下了文章来源地址https://www.toymoban.com/news/detail-494715.html
最后放一下完整的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实现打开影像并以鼠标为中心用滚轮控制图片缩放的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!