赞
踩
使用Qt来画图的时候,需要了解一下QGraphicsView(视图)、QGraphicsScene(场景)、QGraphicsItem(图元),已经他们之间的关系。
通过把各种 图元(基类都是:QGraphicsItem)组合在一起搭建成场景(QGraphicsScene),把搭建好的场景通过视图展示出来(QGraphicsView)。
通过一个示例来展示,选中图元的时候可以移动图元,选中空白的时候可以移动整个场景:
这三者之间的存在不同的坐标系,他们之间需要坐标转换,而且只用QGraphicsItem和QGraphicsView有坐标转换的功能,也就是说QGraphicsItem和QGraphicsView都可以QGraphicsScene直接进行坐标转换,但是QGraphicsItem和QGraphicsView之间的坐标转换需要通过QGraphicsScene进行转换。
所有的图元QGraphicsItem都是放到QGraphicsScene中,所以QGraphicsScene是所有的图元的父图元。
常用的坐标转换函数:
QGraphicsView::mapToScene() - 视图 -> 场景
QGraphicsView::mapFromScene() - 场景 -> 视图
QGraphicsItem::mapFromScene() - 场景 -> 图元
QGraphicsItem::mapToScene() - 图元 -> 场景
QGraphicsItem::mapToParent() - 子图元 -> 父图元
QGraphicsItem::mapFromParent() - 父图元 -> 子图元
QGraphicsItem::mapToItem() - 本图元 -> 其他图元
QGraphicsItem::mapFromItem() - 其他图元 -> 本图元
如果是移动单个图元的话,
setFlag(QGraphicsItem::ItemIsMovable, true);//可以拖动
setFlag(QGraphicsItem::ItemIsSelectable, true);//可以选中
贴上代码:
自定义图元:
#pragma once #include <QGraphicsEllipseItem> class IGraphicsCoord; class AAAEllipseItem : public QGraphicsEllipseItem { public: AAAEllipseItem(QGraphicsItem *parent); ~AAAEllipseItem(); inline void setCoord(IGraphicsCoord* coord){ _graphicsCoord = coord; } private: virtual void mousePressEvent(QGraphicsSceneMouseEvent *event)Q_DECL_OVERRIDE; virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event)Q_DECL_OVERRIDE; virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)Q_DECL_OVERRIDE; private: IGraphicsCoord* _graphicsCoord = nullptr; QPointF _mousePress; };
#include "AAAEllipseItem.h" #include <QDebug> #include <QPen> #include <QGraphicsSceneMouseEvent> #include "IGraphicsCoord.h" AAAEllipseItem::AAAEllipseItem(QGraphicsItem *parent) : QGraphicsEllipseItem(parent) { setFlag(QGraphicsItem::ItemIsMovable, true); setFlag(QGraphicsItem::ItemIsSelectable, true); QPen pen; pen.setColor(QColor(247, 99, 0)); pen.setWidth(3); setPen(pen); } AAAEllipseItem::~AAAEllipseItem() { } void AAAEllipseItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { QGraphicsEllipseItem::mousePressEvent(event); qDebug() << "AAAEllipseItem:" << event->pos().x() << event->pos().y(); QPointF ptScene = mapToScene(event->pos()); qDebug() << "AAAEllipseItem mapToScene:" << ptScene.x() << ptScene.y(); if (_graphicsCoord != nullptr){ _graphicsCoord->itemToSence(ptScene); } } void AAAEllipseItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { QGraphicsEllipseItem::mouseMoveEvent(event); } void AAAEllipseItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { QGraphicsEllipseItem::mouseReleaseEvent(event); }
自定义场景:
#pragma once #include <QGraphicsScene> class AAAGraphicsScene : public QGraphicsScene { Q_OBJECT public: AAAGraphicsScene(QObject *parent); ~AAAGraphicsScene(); private: virtual void mousePressEvent(QGraphicsSceneMouseEvent *event)Q_DECL_OVERRIDE; virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event)Q_DECL_OVERRIDE; virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)Q_DECL_OVERRIDE; };
#include "AAAGraphicsScene.h" #include <QDebug> #include <QGraphicsSceneMouseEvent> AAAGraphicsScene::AAAGraphicsScene(QObject *parent) : QGraphicsScene(parent) { } AAAGraphicsScene::~AAAGraphicsScene() { } void AAAGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event) { QGraphicsScene::mousePressEvent(event); qDebug() << "AAAGraphicsScene:" << event->pos().x() << event->pos().y(); } void AAAGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { QGraphicsScene::mouseMoveEvent(event); } void AAAGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { QGraphicsScene::mouseReleaseEvent(event); }
自定义视图:
#pragma once #include <QGraphicsView> #include "IGraphicsCoord.h" class IGraphicsCoord2; class AAAGraphicsView : public QGraphicsView,public IGraphicsCoord { Q_OBJECT public: AAAGraphicsView(QWidget *parent); ~AAAGraphicsView(); inline void setItemCoord(IGraphicsCoord2* coord){ _graphicsCoord2 = coord; } protected: void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; private: virtual void itemToSence(QPointF pt)override; private: IGraphicsCoord2* _graphicsCoord2 = nullptr; QPoint _mouseLBtnDown; bool _isLBtnDown = false; };
#include "AAAGraphicsView.h" #include <QDebug> #include <QMouseEvent> AAAGraphicsView::AAAGraphicsView(QWidget *parent) : QGraphicsView(parent) { //隐藏水平/竖直滚动条 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); //设置场景范围 setSceneRect(INT_MIN / 2, INT_MIN / 2, INT_MAX, INT_MAX); //反锯齿 setRenderHints(QPainter::Antialiasing); } AAAGraphicsView::~AAAGraphicsView() { } void AAAGraphicsView::mousePressEvent(QMouseEvent *event) { QGraphicsView::mousePressEvent(event); qDebug() << "AAAGraphicsView:" << event->pos().x() << event->pos().y(); if (event->button() == Qt::LeftButton){ if (scene()->itemAt(mapToScene(event->pos()), transform()) == nullptr) {//没有选中任何图元 qDebug() << QStringLiteral("没有选中图元"); _mouseLBtnDown = event->pos(); _isLBtnDown = true; } } } void AAAGraphicsView::mouseMoveEvent(QMouseEvent *event) { QGraphicsView::mouseMoveEvent(event); if (_isLBtnDown){ QPointF ptNow = mapToScene(event->pos()); QPointF movePt = ptNow - mapToScene(_mouseLBtnDown); //根据鼠标当前的点作为定位点 setTransformationAnchor(QGraphicsView::AnchorUnderMouse); QPoint nowCenter(-movePt.x(), -movePt.y()); //qDebug() << "nowCenter:" << nowCenter.x()<< " "<< nowCenter.y(); centerOn((nowCenter)); setTransformationAnchor(QGraphicsView::AnchorViewCenter); } } void AAAGraphicsView::mouseReleaseEvent(QMouseEvent *event) { QGraphicsView::mouseReleaseEvent(event); if (event->button() == Qt::LeftButton) { _isLBtnDown = false; } } void AAAGraphicsView::itemToSence(QPointF pt) { QPointF ptFromScene = mapFromScene(pt); qDebug() << "AAAGraphicsView mapFromSence:" << ptFromScene.x() << ptFromScene.y(); }
定义接口:
#pragma once
#include <QPointF>
class IGraphicsCoord {
public:
IGraphicsCoord();
~IGraphicsCoord();
virtual void itemToSence(QPointF pt);
};
#include "IGraphicsCoord.h"
IGraphicsCoord::IGraphicsCoord() {
}
IGraphicsCoord::~IGraphicsCoord() {
}
void IGraphicsCoord::itemToSence(QPointF pt) {
}
创建场景:
void QtGuiOPenGL::init3() { AAAGraphicsScene* scene = new AAAGraphicsScene(this); AAAEllipseItem* e1 = new AAAEllipseItem(nullptr); e1->setRect(10, 10, 100, 100); scene->addItem(e1); AAAEllipseItem* e2 = new AAAEllipseItem(nullptr); e2->setRect(20, 20, 200, 100); scene->addItem(e2); scene->addLine(0.0, 0.0, 100.0, 0.0); scene->addLine(0.0, 0.0, 0.0, 100.0); AAAGraphicsView* view = new AAAGraphicsView(this); e1->setCoord(view); //view->setAlignment(Qt::AlignLeft | Qt::AlignTop); view->setScene(scene); ui.verticalLayout->addWidget(view) ; }
运行之后,当点击一个图元的时候,输出的信息:
AAAEllipseItem: 54 43
AAAEllipseItem mapToScene: 54 43
AAAGraphicsScene: 54 43
AAAGraphicsView: 357 304
这也说明了,鼠标事件传递的顺序:
图元-> 场景->视图
QGraphicsItem -> QGraphicsScene -> QGraphicsView
视图和图元的交互是通过场景来装换的。
aaa
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。