1.最终效果
Qt 图片交互——鼠标滚轮放缩、拖拽、选点_哔哩哔哩_bilibili
Qt 图片交互——鼠标滚轮放缩、拖拽、选点
2.核心代码说明
技术路线为:
基于QGraphicsView,使用scale函数执行放缩,使用centerOn(mapToScene(QPoint))执行平移,将QImage转化为QPixmap绘制在QGraphicsPixmapItem上。
头文件与源代码均是完整的,可以直接集成到工程中实用。
2.1.头文件
#ifndef HI_GRAPHICSVIEW_H
#define HI_GRAPHICSVIEW_H
#include <QBoxLayout>
#include <QGraphicsView>
#include <qevent.h>
class HI_ImageBox;
class HI_GraphicsView:public QGraphicsView
{
Q_OBJECT
public:
HI_GraphicsView(QWidget *parent = 0);
~HI_GraphicsView();
void Init(HI_ImageBox * imageBox){m_imageBox = imageBox;}
void SetImage(const QImage & image);
protected:
virtual void wheelEvent(QWheelEvent *event) override;
virtual void mouseMoveEvent(QMouseEvent *event) override;
virtual void mousePressEvent(QMouseEvent *event) override;
virtual void mouseReleaseEvent(QMouseEvent *event) override;
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
public slots:
void ZoomIn();
void ZoomOut();
void Zoom(float scaleFactor);
void Translate(QPointF delta);
private:
bool m_isTranslate;
QPoint m_lastMousePos;
HI_ImageBox * m_imageBox;
QGraphicsScene * m_scene;
QGraphicsPixmapItem * m_imageItem;
};
#endif // HI_GRAPHICSVIEW_H
2.2.源代码
#include "hi_graphicsview.h"
#include <QGraphicsPixmapItem>
#include "hi_imagebox.h"
HI_GraphicsView::HI_GraphicsView(QWidget *parent):
QGraphicsView(parent),
m_isTranslate(false),
m_scene(new QGraphicsScene()),
m_imageItem(new QGraphicsPixmapItem())
{
m_scene->addItem(m_imageItem);
setScene(m_scene);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setRenderHint(QPainter::Antialiasing);
setSceneRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX);
setTransformationAnchor(QGraphicsView::AnchorViewCenter);
centerOn(0, 0);
}
HI_GraphicsView::~HI_GraphicsView()
{
m_scene->deleteLater();
delete m_imageItem;
}
void HI_GraphicsView::SetImage(const QImage &image)
{
m_imageItem->setPixmap(QPixmap::fromImage(image));
QPoint newCenter(image.width() / 2 ,image.height()/2);
//设置scene中心到图像中点
centerOn(newCenter);
show();
}
void HI_GraphicsView::wheelEvent(QWheelEvent *event)
{
// 滚轮的滚动量
QPoint scrollAmount = event->angleDelta();
// 正值表示滚轮远离使用者放大负值表示朝向使用者缩小
scrollAmount.y() > 0 ? ZoomIn() : ZoomOut();
}
void HI_GraphicsView::mouseMoveEvent(QMouseEvent *event)
{
if(m_isTranslate)
{
//获取
QPointF mouseDelta = event->pos()-m_lastMousePos;
Translate(mouseDelta);
}
m_lastMousePos = event->pos();
QGraphicsView::mouseMoveEvent(event);
}
void HI_GraphicsView::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
m_isTranslate = true;
m_lastMousePos = event->pos();
}
else if(event->button()==Qt::RightButton)
{
QPointF point = mapToScene(event->pos());
//只有点击图片时才发送
if (scene()->itemAt(point, transform()) != NULL)
{
emit m_imageBox->ImageClick(point.x(),point.y());
}
}
QGraphicsView::mousePressEvent(event);
}
void HI_GraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
m_isTranslate = false;
QGraphicsView::mouseReleaseEvent(event);
}
void HI_GraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
{
centerOn(m_imageItem->pixmap().width()/2,m_imageItem->pixmap().height()/2);
QGraphicsView::mouseDoubleClickEvent(event);
}
void HI_GraphicsView::ZoomIn()
{
Zoom(1.1);
}
void HI_GraphicsView::ZoomOut()
{
Zoom(0.9);
}
void HI_GraphicsView::Zoom(float scaleFactor)
{
// 防止过小或过大
qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
if (factor < 0.07 || factor > 100)
return;
scale(scaleFactor, scaleFactor);
}
void HI_GraphicsView::Translate(QPointF delta)
{
int w = viewport()->rect().width();
int h = viewport()->rect().height();
QPoint newCenter(w / 2. - delta.x()+0.5, h / 2. - delta.y()+0.5);
centerOn(mapToScene(newCenter));
}
其中HI_ImageBox类是做了一个接口,用于将类封装为一个工具库。可根据实际应用状况修改该部分内容。
接口类头文件:
#ifndef HI_IMAGEBOX_H
#define HI_IMAGEBOX_H
#include <QtCore/qglobal.h>
#if defined(HI_IMAGEBOX_LIBRARY)
# define HI_IMAGEBOX_EXPORT Q_DECL_EXPORT
#else
# define HI_IMAGEBOX_EXPORT Q_DECL_IMPORT
#endif
#include <QImage>
#include <QBoxLayout>
class HI_GraphicsView;
/**
* @brief The HI_ImageBox class
* 图片展示控件,封装了图片加载,放缩,选点操作
*/
class HI_IMAGEBOX_EXPORT HI_ImageBox:public QObject
{
Q_OBJECT
public:
HI_ImageBox();
~HI_ImageBox();
/**
* @brief 获取当前控件版本
* @return
*/
QString Version();
/**
* @brief 初始化
* @param panel: 展示图片的容器
*/
void Init(QBoxLayout * panel);
/**
* @brief 获取当前显示的图片
* @return 当前显示的图片
*/
const QImage & GetImage(){return m_image;}
/**
* @brief 设置图片
* @param image: 要显示的图片
*/
void SetImage(const QImage & image);
/**
* @brief 设置图片
* @param image: 要展示图片的地址
*/
void SetImage(const QString & image);
//信号
signals:
/**
* @brief 点击图片的信号
* @param x: 点击的图片X坐标
* @param y: 点击的图片Y坐标
*/
void ImageClick(int x,int y);
//变量
private:
HI_GraphicsView * m_widget; /**< 用于操作绘图的控件*/
QImage m_image; /**< 当前显示图片*/
friend class HI_GraphicsView;
};
#endif // HI_IMAGEBOX_H
接口类源代码:
#include "hi_imagebox.h"
#include "hi_graphicsview.h"
HI_ImageBox::HI_ImageBox():
m_widget(nullptr)
{
}
HI_ImageBox::~HI_ImageBox()
{
if(m_widget)
m_widget->deleteLater();
}
QString HI_ImageBox::Version()
{
return "HI_ImageBox V1.0.21724";
}
void HI_ImageBox::Init(QBoxLayout *panel)
{
if(m_widget!=nullptr)
return;
m_widget = new HI_GraphicsView(nullptr);
if(panel)
panel->addWidget(m_widget);
m_widget->Init(this);
}
void HI_ImageBox::SetImage(const QImage &image)
{
m_image = image;
m_widget->SetImage(image);
}
void HI_ImageBox::SetImage(const QString &image)
{
QImage img = QImage(image);
if(!img.isNull())
{
m_image = img;
m_widget->SetImage(img);
}
}
3.工程源代码(包含demo)
不需要积分,直接下载: