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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM