zoukankan      html  css  js  c++  java
  • 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;
    }

     

  • 相关阅读:
    PAT 1008--------数组元素的循环右移,你需要记住的
    PAT1049-----枚举法,找规律题,注意降低时间复杂度
    PAT1048----你需要了解并记住的解题思路
    C++中几个输入函数的用法和区别(cin、cin.get()、cin.getline()、getline()、gets()、getchar()))
    PAT1040----关于数学题目的解法新思路值得借鉴,字符的配对
    PAT1029-----介绍字符串的解题思路和部分知识点
    PAT1027-----等差数列的问题或数学问题
    PAT1026----四舍五入的思路,%2d的一些知识
    / 已阅 /PAT1017-------高精度计算,问题的所有可能情况
    LeetCode 无重复字符的最长子串
  • 原文地址:https://www.cnblogs.com/ohsolong/p/12807103.html
Copyright © 2011-2022 走看看