QGraphicsView, QGraphicsObject ,QQGraphicsSvgItem 图片接收鼠标事件 拖拉 收放

由于项目要求,需要加载svg格式图片和pixmap图片,并根据指定坐标在图上进行勾画,并且对相应位置接收鼠标事件。

-继承QGraphicsObject,实现加载pixmap的项

myimageitem.h

#ifndef MYIMAGEITEM_H
#define MYIMAGEITEM_H
#include <QGraphicsObject>
#include <QPainter>
#include <QVector>
#include <QGraphicsSceneMouseEvent>
#include <QMap>

class myimageitem: public QGraphicsObject
{
    Q_OBJECT
public:
    myimageitem(QRectF, rect,const QPixmap &image,QGraphicsObject *parent = nullptr);//rect 项的边框尺寸,image 图像
    ~myimageitem();

    void setRect(const QRectF &rect);

    QRectF boundingRect()const override;
    void paint(QPainter *panter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
public slots:
    void onSyn(int id);

signals:
    void syn(int id); 
private:
    QRectF m_rect;
    QPixmap m_pixmap;
    float deltaX; // 显示窗口大小与实际图片横轴比例
    float deltaY; // 显示窗口大小与实际图片竖轴比例
    QMap<int, bool> _rectPointSelected;// 标记矩形是否被鼠标事件选中
    QMap<int,QRectF> _rectPoint; // 保存矩形数据
};

#endif // MYIMAGEITEM_H
#include "myimageitem.h"

myimageitem::myimageitem(QRectF rect,const QPixmap &image, QGraphicsObject * parent):QGraphicsObject(parent),m_pixmap(image)
{
    deltaX = rect.width()/m_pixmap.width();
    deltaY = rect.height()/m_pixmap.height();
    QRectF rect1(0,0,200*deltaX,200*deltaY);
    QRectF rect2(200*deltaX, 200*deltaY, 200*deltaX, 200*deltaY);
  // 初始化测试坐标数据 _rectPoint.insert(
0, rect1); _rectPointSelected.insert(0,false); _rectPoint.insert(1,rect2); _rectPointSelected.insert(1,false); setRect(rect); } myimageitem::~myimageitem(){ } void myimageitem::setRect(const QRectF &rect) { if(m_rect == rect){ return; } prepareGeometryChange(); m_rect = rect; update(); // 通知重绘图片 } QRectF myimageitem::boundingRect() const{ return m_rect; // 边界尺寸 } void myimageitem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ Q_UNUSED(option); Q_UNUSED(widget); painter->setRenderHint(QPainter::Antialiasing, true); // 打开抗锯齿 painter->save(); painter->drawPixmap(m_rect, m_pixmap,QRectF()); // 画图 for(QMap<int, bool>::iterator it = _rectPointSelected.begin(); it != _rectPointSelected.end(); ++it){ if(!it.value()){ painter->setPen(Qt::blue); // 如果未被选中 }else { painter->setPen(Qt::red); // 如果被选中 it.value() = false; // 重绘之后选中状态重置 } painter->drawRect(_rectPoint[it.key()]); // 绘制矩形 } painter->restore(); } void myimageitem::mousePressEvent(QGraphicsSceneMouseEvent *event){ // 接收鼠标事件 if(event->button() == Qt::LeftButton){ for(QMap<int, QRectF>::iterator it = _rectPoint.begin(); it != _rectPoint.end(); ++it){ if(it.value().contains(event->pos())){ prepareGeometryChange();// 保持项的索引,即使改变了项的尺寸,如果有必要会调用update() _rectPointSelected[it.key()] = true; // 选中矩形 // emit syn(it.key()); } } } } void myimageitem::onSyn(int id){ prepareGeometryChange(); _rectPointSelected[id] = true; update(); }

-继承QGraphicsSvgItem

mygriditem.h

#ifndef MYGRIDITEM_H
#define
MYGRIDITEM_H #include <QtSvg/QGraphicsSvgItem> #include <QGraphicsSceneMouseEvent> #include <QtSvg/QSvgRenderer> #include <QPainter> class mygriditem :public QGraphicsSvgItem {
Q_OBJECTpublic: mygriditem(QRectF boundRect,const QString &svgFile,const QSize svgSize,QGraphicsSvgItem *parent = nullptr);// 导入svg格式图片文件 和尺寸 ~mygriditem(); QRectF boundingRect()const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)override; signals: void syn(int id); public slots: void onSyn(int id); protected: void mousePressEvent(QGraphicsSceneMouseEvent *event) override; private: QRectF _boundRect; // 边界矩形 QSvgRenderer *_svgRender; float _xDelta; float _yDelta; QMap<int, bool> _rectPointSelected; QMap<int,QRectF> _rectPoint; }; #endif // MYGRIDITEM_H
#include "mygriditem.h"

mygriditem::mygriditem(QRectF boundRect,const QString &svgFile,const QSize svgSize ,QGraphicsSvgItem *parent):QGraphicsSvgItem(parent),
    _boundRect(boundRect)
{
    _svgRender = new QSvgRenderer(svgFile); //加载svg图


    _xDelta = _boundRect.width()/svgSize.width();
    _yDelta = _boundRect.height()/ svgSize.height();

    QRectF rect1(0*_xDelta,0*_yDelta,60*_xDelta,60*_yDelta);
    QRectF rect2(60*_xDelta,60*_yDelta,60*_xDelta,60*_yDelta);
    _rectPoint.insert(0, rect1);
    _rectPoint.insert(1 ,rect2);
    _rectPointSelected.insert(0, false);
    _rectPointSelected.insert(1, false);
}

mygriditem::~mygriditem(){

}

void mygriditem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
    Q_UNUSED(option);
    Q_UNUSED(widget);
    painter->setRenderHint(QPainter::Antialiasing, true);
    painter->save();
    _svgRender->render(painter, _boundRect); // 绘制svg图片
//    QGraphicsSvgItem::paint(painter, option, widget);
    for(QMap<int,bool>::iterator it = _rectPointSelected.begin(); it != _rectPointSelected.end() ;++it){
        if(it.value()){
            painter->setPen(Qt::red);
            it.value() = false;
        }else {
            painter->setPen(Qt::green);
        }
        painter->setBrush(Qt::green);
        painter->drawRect(_rectPoint[it.key()]);
    }
    painter->restore();
}

QRectF mygriditem::boundingRect() const{
    return _boundRect;
}

void mygriditem::mousePressEvent(QGraphicsSceneMouseEvent *event){
    if(event->button() == Qt::LeftButton){
        for(QMap<int, QRectF>::iterator it = _rectPoint.begin(); it != _rectPoint.end(); ++ it){
            if(it.value().contains(event->pos())){
                prepareGeometryChange();
                _rectPointSelected[it.key()] = true;
                update();
 //               emit syn(it.key());
            }
        }
    }
}
void mygriditem::onSyn(int id){
    prepareGeometryChange();
    _rectPointSelected[id] = true;
    update();
}

-继承QGraphicsView 实现缩放 拖拽(这部分参考其它博主)

mygraphicsview.h

#ifndef MYGRAPHICSVIEW_H
#define MYGRAPHICSVIEW_H

#include <QGraphicsView>
#include <QKeyEvent>

class mygraphicsview:public QGraphicsView
{
public:
    explicit mygraphicsview(QWidget *parent = nullptr);
    ~mygraphicsview();


      // 平移速度
    void setTranslateSpeed(qreal speed);
    qreal translateSpeed() const;

    // 缩放的增量
    void setZoomDelta(qreal delta);
    qreal zoomDelta() const;
  protected:
      // 上/下/左/右键向各个方向移动、加/减键进行缩放、空格/回车键旋转
      void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
      // 平移
      void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
      void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
      void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
      // 放大/缩小
      void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;

  public Q_SLOTS:
      void zoomIn();  // 放大
      void zoomOut();  // 缩小
      void zoom(float scaleFactor); // 缩放 - scaleFactor缩放的比例因子
      void translate(QPointF delta);  // 平移

  private:
      Qt::MouseButton m_translateButton;  // 平移按钮
      qreal m_translateSpeed;  // 平移速度
      qreal m_zoomDelta;  // 缩放的增量
      bool m_bMouseTranslate;  // 平移标识
      QPoint m_lastMousePos;  // 鼠标最后按下的位置
      qreal m_scale;  // 缩放值
};

#endif // MYGRAPHICSVIEW_H
#include "mygraphicsview.h"

#define VIEW_CENTER viewport()->rect().center()
#define VIEW_WIDTH  viewport()->rect().width()
#define VIEW_HEIGHT viewport()->rect().height()


mygraphicsview::mygraphicsview(QWidget *parent):QGraphicsView(parent),
  m_translateButton(Qt::LeftButton),
        m_scale(1.0),
        m_zoomDelta(0.1),
        m_translateSpeed(1.0),
        m_bMouseTranslate(false)
{
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
       setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
       setCursor(Qt::PointingHandCursor);
       setRenderHint(QPainter::Antialiasing);

//       setSceneRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX);
//       setSceneRect(0,0,5472, 3648);
//       centerOn(0, 0);


}

mygraphicsview::~mygraphicsview(){

}

// 平移速度
void mygraphicsview::setTranslateSpeed(qreal speed)
{
    // 建议速度范围
    Q_ASSERT_X(speed >= 0.0 && speed <= 2.0,
               "InteractiveView::setTranslateSpeed", "Speed should be in range [0.0, 2.0].");
    m_translateSpeed = speed;
}

qreal mygraphicsview::translateSpeed() const
{
    return m_translateSpeed;
}

// 缩放的增量
void mygraphicsview::setZoomDelta(qreal delta)
{
    // 建议增量范围
    Q_ASSERT_X(delta >= 0.0 && delta <= 1.0,
               "InteractiveView::setZoomDelta", "Delta should be in range [0.0, 1.0].");
    m_zoomDelta = delta;
}

qreal mygraphicsview::zoomDelta() const
{
    return m_zoomDelta;
}


// 上/下/左/右键向各个方向移动、加/减键进行缩放、空格/回车键旋转
void mygraphicsview::keyPressEvent(QKeyEvent *event)
{
    switch (event->key()) {
    case Qt::Key_Up:
        translate(QPointF(0, -2));  // 上移
        break;
    case Qt::Key_Down:
        translate(QPointF(0, 2));  // 下移
        break;
    case Qt::Key_Left:
        translate(QPointF(-2, 0));  // 左移
        break;
    case Qt::Key_Right:
        translate(QPointF(2, 0));  // 右移
        break;
    case Qt::Key_Plus:  // 放大
        zoomIn();
        break;
    case Qt::Key_Minus:  // 缩小
        zoomOut();
        break;
    case Qt::Key_Space:  // 逆时针旋转
        rotate(-5);
        break;
    case Qt::Key_Enter:  // 顺时针旋转
    case Qt::Key_Return:
        rotate(5);
        break;
    default:
        QGraphicsView::keyPressEvent(event);
    }
}

// 平移
void mygraphicsview::mouseMoveEvent(QMouseEvent *event)
{
    if (m_bMouseTranslate){
        QPointF mouseDelta = mapToScene(event->pos()) - mapToScene(m_lastMousePos);
        translate(mouseDelta);
    }

    m_lastMousePos = event->pos();

    QGraphicsView::mouseMoveEvent(event);
}

void mygraphicsview::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == m_translateButton) {
        // 当光标底下没有 item 时才能移动
        QPointF point = mapToScene(event->pos());
        if (scene()->itemAt(point, transform()) != NULL)  {
            m_bMouseTranslate = true;
            m_lastMousePos = event->pos();
        }
    }

    QGraphicsView::mousePressEvent(event);
}

void mygraphicsview::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == m_translateButton)
        m_bMouseTranslate = false;

    QGraphicsView::mouseReleaseEvent(event);
}

// 放大/缩小
void mygraphicsview::wheelEvent(QWheelEvent *event)
{
    // 滚轮的滚动量
    QPoint scrollAmount = event->angleDelta();
    // 正值表示滚轮远离使用者放大负值表示朝向使用者缩小
    scrollAmount.y() > 0 ? zoomIn() : zoomOut();
}

// 放大
void mygraphicsview::zoomIn()
{
    zoom(1 + m_zoomDelta);
}

// 缩小
void mygraphicsview::zoomOut()
{
    zoom(1 - m_zoomDelta);
}

// 缩放 - scaleFactor缩放的比例因子
void mygraphicsview::zoom(float scaleFactor)
{
    // 防止过小或过大
    qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
    if (factor < 0.5 || factor > 100)
        return;

    scale(scaleFactor, scaleFactor);
    m_scale *= scaleFactor;
}

// 平移
void mygraphicsview::translate(QPointF delta)
{
    // 根据当前 zoom 缩放平移数
    delta *= m_scale;
    delta *= m_translateSpeed;

    // view 根据鼠标下的点作为锚点来定位 scene
    setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
    QPoint newCenter(VIEW_WIDTH / 2 - delta.x(),  VIEW_HEIGHT / 2 - delta.y());
    centerOn(mapToScene(newCenter));

    // scene 在 view 的中心点作为锚点
    setTransformationAnchor(QGraphicsView::AnchorViewCenter);
}

-测试代码

cview.h

#ifndef CVIEW_H
#define CVIEW_H

#include <QWidget>
#include <QGraphicsScene>
#include <QtSvg/QSvgRenderer>
#include <QtSvg/QGraphicsSvgItem>
#include<QGraphicsGridLayout>
#include <QGraphicsLayout>
#include "mygraphicsview.h"
#include "myimageitem.h"
#include "mygriditem.h"

QT_BEGIN_NAMESPACE
namespace Ui { class CView; }
QT_END_NAMESPACE

class CView : public QWidget
{
    Q_OBJECT

public:
    CView(QWidget *parent = nullptr);
    ~CView();

private:
    Ui::CView *ui;
    QGraphicsScene *_scene;
    QGraphicsObject *_codeImgae;
};
#endif // CVIEW_H
#include "cview.h"
#include "./ui_cview.h"

CView::CView(QWidget *parent)
    : QWidget(parent),
    ui(new Ui::CView),
    _scene(new QGraphicsScene)

{
    ui->setupUi(this);
    QPixmap pixmap;
    pixmap.load("XXX.png"); // 传入自己的图片
    float pixWidth = pixmap.width();
    float pixHeight = pixmap.height();
    float deltaX = ui->graphicsView_2->width()/pixWidth;
    float deltaY = ui->graphicsView_2->height()/pixHeight;

    int viewW = ui->graphicsView_2->width();
    int viewH = ui->graphicsView_2->height();

    _codeImgae = new myimageitem(QRectF(0, 0,viewH, viewH),pixmap);
    _scene->addItem(_codeImgae);
    ui->graphicsView_2->setScene(_scene);
    float w = ui->graphicsView->width();
    float h = ui->graphicsView->height();
     mygriditem *svg_render = new mygriditem(QRectF(0,0,w,h),QString("XXX.svg"));// 传入自己的图片
    QGraphicsScene *svgScene = new QGraphicsScene();


    svgScene->addItem(svg_render);

    QList<QGraphicsItem*> items = svgScene->items();
    ui->graphicsView->setScene(svgScene);
}

CView::~CView()
{
    delete ui;
}

 

posted @ 2020-04-30 10:07  梁子~  阅读(1549)  评论(0编辑  收藏  举报