QGraphicsView实现拖拽缩放

20221104_094101

首先创建视图框架,分别是QGraphicsView、QGraphicsScene和QGraphicsItem。
其中QGraphicsItem需要继承重写,重写的派生类中必须需要实现两个函数,paint(item的绘制函数)和boundingRect(item的大小位置函数),因为这两个是纯虚函数。

然后在view视图中添加Scene。设置view的
setDragMode打开拖拽功能。设置view的setTransform实现缩放功能。

示例代码如下,该示例支持按钮缩放,滚轮缩放和鼠标拖拽。

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "mgraaphicsview.h"

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    MGraaphicsView* m_view = nullptr;
};

#endif // WIDGET_H

#include "widget.h"

#include <QPushButton>
#include <QGridLayout>
#include <QDebug>

Widget::Widget(QWidget *parent) :
    QWidget(parent)
{
    QPushButton* bbtn = new QPushButton("放大",this);
    QPushButton* sbtn = new QPushButton("缩小",this);
    QPushButton* obtn = new QPushButton("还原",this);
    QGraphicsScene* scene = new QGraphicsScene();
    m_view = new MGraaphicsView(scene);

    QGridLayout* lay = new QGridLayout(this);
    lay->addWidget(m_view,0,0,10,10);
    lay->addWidget(bbtn,10,0,1,1);
    lay->addWidget(sbtn,10,1,1,1);
    lay->addWidget(obtn,10,2,1,1);
    lay->setMargin(0);
    this->setLayout(lay);

    connect(bbtn,&QPushButton::clicked,this,[=]()
    {
        m_view->zoomOnce(1);
    });
    connect(sbtn,&QPushButton::clicked,this,[=]()
    {
        m_view->zoomOnce(-1);
    });
    connect(obtn,&QPushButton::clicked,this,[=]()
    {
    });

}

Widget::~Widget()
{
}


view视图框架类,相当于显示窗口,给它添加QGraphicsScene,使其拥有界面,且可以添加多个QGraphicsScene。
setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);和
setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);隐藏滚动条。

#ifndef MGRAAPHICSVIEW_H
#define MGRAAPHICSVIEW_H

#include <QGraphicsView>
#include <QWheelEvent>
#include "mgraphicsitem.h"

class MGraaphicsView : public QGraphicsView
{
public:
    MGraaphicsView(QGraphicsScene *scene, QWidget *parent = nullptr);
    void wheelEvent(QWheelEvent *event);
    void zoomOnce(int val);

    int m_minZoom;
    int m_maxZoom;
    int m_zoom = 0;
    double m_zoomnum = 1;

    MGraphicsItem* _item = nullptr;
};

#endif // MGRAAPHICSVIEW_H
#include "mgraaphicsview.h"
#include <qmath.h>
#include <QDebug>

MGraaphicsView::MGraaphicsView(QGraphicsScene *scene, QWidget *parent)
    :QGraphicsView(scene,parent)
{
    setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);

    setDragMode(QGraphicsView::ScrollHandDrag);
    setTransformationAnchor(QGraphicsView::AnchorUnderMouse);

    _item = new MGraphicsItem();
    _item->setboundingRect(0,0,1000,1000);
    scene->addItem(_item);
}

void MGraaphicsView::wheelEvent(QWheelEvent *event)
{
    event->accept();
    zoomOnce(event->delta());
}

void MGraaphicsView::zoomOnce(int val)
{
    if (val > 0)
    {
        m_zoom++;
        auto scaleValue = qPow(2, m_zoom);
        setTransform(QTransform::fromScale(scaleValue, scaleValue));
    }
    else
    {
        m_zoom--;
        auto scaleValue = qPow(2, m_zoom);
        setTransform(QTransform::fromScale(scaleValue, scaleValue));
    }
}

QGraphicsItem类,它是界面上的控件,相对于Qt的标准控件,它更省内存。且在中QGraphicsScene中也可以添加QT标准控件。通过addWidget即可。如下

		QWidget *w = new QWidget ()
        QGraphicsProxyWidget* pwidget = m_mapView->scene()->addWidget(w);
        pwidget->setFlag(QGraphicsItem::ItemIgnoresTransformations, true); //禁止随界面缩放而缩放
        pwidget->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); //禁止随界面大小变化而变化

继承QGraphicsItem实现的自定义Item,由于QGraphicsItem它不继承QObject,所有它不具备信号槽机制,如果想要实现信号槽,可以多重继承,既继承QObject,又继承QGraphicsItem,就像QGraphicsObject它一样。

#ifndef MGRAPHICSITEM_H
#define MGRAPHICSITEM_H

#include <QGraphicsItem>
#include <QPainter>
#include <QSvgRenderer>

class MGraphicsItem : public QGraphicsItem
{
public:
    MGraphicsItem();
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr);
    virtual QRectF boundingRect() const ;

    void setboundingRect(int x, int y, int w, int h);

    int m_x = 0;
    int m_y = 0;
    int m_w = 0;
    int m_h = 0;
    QSvgRenderer* _renderer = nullptr;
    void reLoad(QString name);
};

#endif // MGRAPHICSITEM_H

#include "mgraphicsitem.h"

MGraphicsItem::MGraphicsItem()
{
    _renderer = new QSvgRenderer;
    _renderer->load(QString("test.svg"));
}

void MGraphicsItem::reLoad(QString name)
{
    _renderer->load(name);
}

void MGraphicsItem::setboundingRect(int x,int y,int w,int h)
{
    m_x = x;
    m_y = y;
    m_w = w;
    m_h = h;
}

void MGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    if (!_renderer->isValid())
        return;

    _renderer->render(painter, boundingRect());
}

QRectF MGraphicsItem::boundingRect() const
{
    return QRectF(m_x,m_y,m_w,m_h);
}

QSvgRenderer它是用来显示svg矢量图的一个代理类。

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东方忘忧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值