一.加载显示图片
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)。
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);
五.开源示例