一.加载显示图片

1.1 创建QGraphicsPixmapItem、QGraphicsScene

建议使用new创在堆区,PixmapItem设为成员变量(避免可能的加载失败)。

m_GraphPixItem = new QGraphicsPixmapItem(nullptr);//有几率会崩 oeGraphicsPixmapItem
    m_GraphPixItem->setAcceptHoverEvents(true);//为图元QGraphicsPixmapItem设置鼠标不点击也捕捉鼠标移动事件
    m_GraphScene = new QGraphicsScene;
    m_GraphScene->addItem(m_GraphPixItem);
    ui->graphicsView->setScene(m_GraphScene);

    QImage img = cvMat2QImage(mat8);
    m_GraphPixItem->setPixmap(QPixmap::fromImage(img));//推荐放最后,避免无图

1.2 设置打开时缩放比例(使图像略小于控件)

A.构造函数中(长宽不为设定值,也不建议进行缩放等相关操作,fitInView后坐标不符合预期):

B.界面展开显示后/resizeEvent函数中:
rect() =打开后为控件正常设置宽高(400,560,0,0),不再随缩放改变长宽。
Rectf=(400,560,0,0)或(400,560,-199,-279),

QRectF bounds = scene->itemsBoundingRect();//图1000x1400 Rectf=(400,560,-199,-279)
    bounds.setWidth(bounds.width()*1.);         // to tighten-up margins
    bounds.setHeight(bounds.height()*1.);       // same as above
    ui->graphicsView->fitInView(bounds, Qt::KeepAspectRatio);//Rectf=(1015,1421,-5,-7)
    //ui->graphicsView->setSceneRect(bounds);//Rectf=(400,560,0,0)
    //ui->graphicsView->scene()->setSceneRect(bounds);//Rectf=(400,560,0,0)
    ui->graphicsView->centerOn(0, 0);//不影响Rectf

1.3 QGraphScene导出为图片

void GraphicsView::ExportSceneSlot(QString sPath)
{
    QImage image(m_GraphScene->width(),m_GraphScene->height(),QImage::Format_ARGB32);//QImage::Format_RGB32
    QPainter painter(&image);
    painter.setRenderHint(QPainter::Antialiasing);
    m_GraphScene->render(&painter);
    QString pngName = sPath+"/Draw.jpg";
    bool saveSuccess = image.save(pngName);
    Q_ASSERT(saveSuccess == true);
}

1.4 属性设置

setViewportUpdateMode(QGraphicsView::FullViewportUpdate);//去掉Item可能存在的拖动重影

支持拖拽(QWidget支持拖拽事件需设置属性和重写函数。)

setAcceptDrops(true);//设置属性
void dragEnterEvent(QDragEnterEvent*event);//拖动进入事件
void dropEvent(QDropEvent*event);

void dragMoveEvent(QDragMoveEvent *event);//连续拖拽

二.常用知识点及功能

2.1 鼠标事件的传导顺序:【view】->【scene分类】->【item】。

A.View和Scene同时重写mousePressEvent,仅View响应。
解决方式:在mousePressEvent下调用基类同名函数。

void MyGraphicsView::mousePressEvent(QMouseEvent * e)
{   
    QGraphicsView::mousePressEvent(e) ;// forward to scene (via default view behaviour)
    // ...
}

B.View重写mousePressEvent,item的mousePressEvent响应情况。
View加mousePressEvent,item的mousePressEvent会响应,不加则不会响应。
C.mouseMoveEvent函数中提前return,导致不按鼠标中心点缩放
猜测未将坐标传至scene,return前加mouseMoveEvent。
D.继承QAbstractGraphicsShapeItem时,重写虚函数为mouseMoveEvent(QGraphicsmouseMoveEvent )。
测面验证【scene分类】->【item】

2.2 QGraphicsItem随鼠标拖动

QGraphicsItem鼠标拖动(设置属性或重写事件)

2.3 坐标(场景坐标,视图坐标)

A.视图坐标(event坐标、控件等)

contentsRect();//较rect()两边各减1。
viewport();//为控件像素宽width()高height()-1

B.视图坐标转场景坐标

event->scenePos();
mapToScene(event->pos());
//求场景高度
mapToScene(contentsRect()).boundingRect().height();//contentsRect()转Scene为boundingRect(),和sceneRect()不一样

2.4 鼠标缩放(以鼠标点为中心)

//QWheelEvent(angleDelta)。QGraphicsSceneWheelEvent(delta)

event->angleDelta;//(0.-120)其y()正(放大)负值可作为判断是否缩放
event->Delta;//=event->angleDelta.y()

以鼠标点为中心:
A.参考QGraphicsView::centerOn
QGraphicsView 如何实现百度地图按照鼠标点进行放大缩小效果(参考QGraphicsView::centerOn) B.参考Asap,两次centerOn
C.设置属性(推荐)

setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setResizeAnchor(QGraphicsView::AnchorUnderMouse);

QT QGraphicsView 在鼠标点击处进行放大缩小

三.进阶

3.1 QGraphicsView缓存刷新(QGraphicsItem::CacheMode,QPixmapCache)。

Qt图形视图框架:QGraphicsView

QGraphicsItem::setZValue

setZvalue()来设置一个item的Z值。默认的Z值是0,具有同样的Z值的item会按照插入的顺序来入栈(stack order)。也就是说,GraphicsView会优先根据item的Z值决定item的层次,只有当Z值相同的情况下才会去理会stack order;
Qt QGraphicsItem的z值怎么用,如何确定上下层关系

四.异常问题记录

4.1 QImage的load加载invalid。

解决方法:缺少dll库,debug下添加imageformats文件夹(本人用的windeployqt生成)。

4.2 部分情况加载失败,-nan 。

1.场景改为成员变量+new分配内存,猜测该种方式内存分配大、权限高,可支持灵活加载大图。
2.类似除0这种数字越界。

4.3 重写QGraphicsItem。

1.需重写纯虚函数boundingRect。
2.继承增加QObject和增加Q_OBJECT宏。

class UICanvasItemBase : public QObject, public QGraphicsItem
{
    Q_OBJECT
protected:
    QRectF boundingRect() const override;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) final;
}

4.4 重写QGraphicsScene的paintEvent(QPaintEvent* event)。

1.因父类无paintEvent导致无this指针。

4.5 高分辨率屏兼容(contentsRect高度会改变)。

放小会调小。
屏幕分辨率3840x2160(contentsRect高度1807)。
屏幕分辨率1920x10800(contentsRect高度777)。

4.6 QDialog中QGraphicsView的move事件不响应。

设置二属性

ui->graphicsView->setMouseTracking(true);
ui->graphicsView->viewport()->installEventFilter(this);

五.开源示例

Draw_Figure(图元绘制及交互)