Qt 图片鼠标滚轮放缩、鼠标拖动平移、单击选点(附工程及源代码)

1.最终效果

Qt 图片交互——鼠标滚轮放缩、拖拽、选点_哔哩哔哩_bilibili

Qt 图片交互——鼠标滚轮放缩、拖拽、选点

2.核心代码说明

技术路线为:

基于QGraphicsView,使用scale函数执行放缩,使用centerOn(mapToScene(QPoint))执行平移,将QImage转化为QPixmap绘制在QGraphicsPixmapItem上。

头文件与源代码均是完整的,可以直接集成到工程中实用。

2.1.头文件

#ifndef HI_GRAPHICSVIEW_H
#define HI_GRAPHICSVIEW_H

#include 
#include 
#include 

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 
#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 

#if defined(HI_IMAGEBOX_LIBRARY)
#  define HI_IMAGEBOX_EXPORT Q_DECL_EXPORT
#else
#  define HI_IMAGEBOX_EXPORT Q_DECL_IMPORT
#endif

#include 
#include 

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)

不需要积分,直接下载

Qt图片交互——鼠标滚轮放缩、拖拽、选点-C++文档类资源-CSDN下载

你可能感兴趣的:(Qt,qt)