当前位置:   article > 正文

基于QGraphicsView、QGraphicsScene、自定义QGraphicsItem的小demo(正矩形、旋转矩形及圆形)_item->move(qpointf(rect.right(), rect.top() + rect

item->move(qpointf(rect.right(), rect.top() + rect.height() / 2));

网上有很多关于这三个的资料,这方面的功能不做过多的描述,仅仅将在做小Demo过程中遇到的问题做下记录,下面是Demo的界面图:

Demo的初衷是不想每次使用QGraphicsView和QGraphicsScene都重写,可以直接拿来使用,后来慢慢加了一些图形项,因为其实是为了熟悉QGpaphicsXX,所以目前只加了3种(正矩形,旋转矩形、圆),刚好这个Demo也练习了一种设计模式——工厂模式,现在就讲些步骤及遇到的问题(只贴关键的代码,整体代码看最后下载链接):

一、以鼠标为中心进行缩放

QGraphicsView和QGraphicsScene(后面简称View和Scene)都是要重写的,这一部分我主要放在View中实现,主要重写滚轮事件 wheelEvent(QWheelEvent * event),代码(部分)如下:

  1. void MyGraphicsView::wheelEvent(QWheelEvent * event)
  2. {
  3. if (this->scene()->items().size() == 0)
  4. return;
  5. QPointF curPoint = event->pos();
  6. QPointF scenePos = this->mapToScene(QPoint(curPoint.x(), curPoint.y()));
  7. qreal viewWidth = viewport()->width();
  8. qreal viewHeight = viewport()->height();
  9. qreal hScale = curPoint.x() / viewWidth;
  10. qreal vScale = curPoint.y() / viewHeight;
  11. int wheelDeltaValue = event->delta();
  12. // 当前放缩倍数;
  13. qreal scaleFactor = this->matrix().m11();
  14. if ((scaleFactor < 0.4 && wheelDeltaValue<0)||(scaleFactor>50 &&wheelDeltaValue>0))
  15. return;
  16. wheelDeltaValue > 0 ? scale(1.2, 1.2) : scale(1.0/1.2, 1.0/1.2);
  17. // 将scene坐标转换为放大缩小后的坐标;
  18. QPointF viewPoint = this->matrix().map(scenePos);
  19. this->horizontalScrollBar()->setValue(int(viewPoint.x() - viewWidth * hScale ));
  20. this->verticalScrollBar()->setValue(int(viewPoint.y() - viewHeight * vScale ));
  21. update();
  22. }

这段代码其实是通过控制ScrollBar来达到目的,但是其实可以不需要这么做,只需要在构造函数中设置属性即可,构造函数如下:

  1. MyGraphicsView::MyGraphicsView(QWidget *parent)
  2. : QGraphicsView(parent)
  3. {
  4. setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // 去掉滚动条
  5. setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  6. setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
  7. setRenderHints(QPainter::Antialiasing);
  8. /*以鼠标中心进行缩放*/
  9. setMouseTracking(true);
  10. setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
  11. setResizeAnchor(QGraphicsView::AnchorUnderMouse);
  12. /********************/
  13. }

构造函数中的后三句才是重点。之所以还留着滚轮事件中ScrollBar->setValue()是发现在放大过程中放大到一定程度,加载进去的图片就“消失”。

注:在Scene中要设置SceneRect的大小,尽量大,具体看后面附带的代码下载链接;

二、绘制不随窗口变化大小的背景

Demo带有棋盘格的背景,实现是重写View的drawBackground(QPainter * painter, const QRectF & rect);

  1. void MyGraphicsView::drawBackground(QPainter * painter, const QRectF & rect)
  2. {
  3. //绘制背景
  4. int wid = this->geometry().width();
  5. int hei = this->geometry().height();
  6. m_ptCenter = this->mapToScene(wid / 2, hei / 2);
  7. QPixmap pix(wid, hei);
  8. QPainter pter(&pix);
  9. QColor clr_white(Qt::white);
  10. QColor clr_gray(240, 240, 240, 240);
  11. int spacing = 15;
  12. QColor useColor;
  13. for (int i = 0; i <= floor(wid / spacing); i++)
  14. {
  15. for (int j = 0; j <= floor(hei/ spacing); j++)
  16. {
  17. useColor = ((i + j) % 2 == 0 ? clr_white : clr_gray);
  18. pter.fillRect(i*spacing, j*spacing, spacing, spacing, useColor);
  19. }
  20. }
  21. painter->drawImage(rect, pix.toImage());
  22. }

三、加载自定义图像Item

自定义图像item其实就是继承QGraphicsItem,由于代码里加了很多图形item,只显示部分;

  1. QRectF MyGraphicsImageItem::boundingRect() const
  2. {
  3. return QRectF(-m_Pixmap.width() / 2, -m_Pixmap.height() / 2, m_Pixmap.width(), m_Pixmap.height());
  4. }
  5. void MyGraphicsImageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
  6. {
  7. Q_UNUSED(option);
  8. Q_UNUSED(widget);
  9. QPen pen = painter->pen();
  10. pen.setWidth(0);
  11. pen.setStyle(Qt::SolidLine);
  12. pen.setColor(QColor(0, 255, 255, 100));
  13. painter->setPen(pen);
  14. painter->setBrush(QColor(0, 0, 255, 100));
  15. painter->drawPixmap(-m_Pixmap.width() / 2, -m_Pixmap.height() / 2, m_Pixmap);
  16. }

四、在图像Item上绘制图形item

1、图形边缘控制点

边缘控制点其实也是自定义的Item,定义为MyCornerItem,该Item不随视图的缩放而缩放,需要更新移动后item的位置:

  1. #pragma once
  2. #ifndef MY_CORNER_ITEM_H
  3. #define MY_CORNER_ITEM_H
  4. #include <QAbstractGraphicsShapeItem>
  5. #include <QGraphicsSceneHoverEvent>
  6. #include <QPainter>
  7. #include <QCursor>
  8. #include <QGraphicsItem>
  9. enum CustomType {
  10. TypeImage = 65536 + 1,
  11. TypeCorner = 65536 + 2,
  12. TypeRect,
  13. TypeRotateRect,
  14. TypeCircle
  15. };
  16. constexpr int CORNER_SIZE = 3;
  17. enum SelectionHandleState
  18. {
  19. SelectionHandleOff,
  20. SelectionHandleInactive,
  21. SelectionHandleActive
  22. };
  23. enum CornerDirction //鼠标经过时的形状
  24. {
  25. None = 0,
  26. LeftTop,
  27. Top,
  28. RightTop,
  29. Right,
  30. RightBottom,
  31. Bottom,
  32. LeftBottom,
  33. Left,
  34. Rotation, //旋转
  35. };
  36. class MyCornerItem : public QAbstractGraphicsShapeItem
  37. {
  38. /*Q_OBJECT*/
  39. public:
  40. explicit MyCornerItem(QGraphicsItem *parent, QPointF point, CornerDirction dir, bool control = false);
  41. virtual ~MyCornerItem() {};
  42. bool hitTest(const QPointF &point);
  43. CornerDirction getDir() const { return m_Dir; }
  44. void setState(SelectionHandleState state);
  45. void move(QPointF point);
  46. void cornerTranslate(QPointF point);
  47. inline void setSelectState(bool bState) { m_bSelect = bState; }
  48. inline bool getSelectState() { return m_bSelect; }
  49. inline QPointF getPointCenter() { return m_point; }
  50. virtual int type() const { return TypeCorner; }
  51. private:
  52. QBrush m_brush;
  53. QPointF m_point;
  54. CornerDirction m_Dir;
  55. SelectionHandleState m_State;
  56. QCursor m_RotateCursor; //旋转图标
  57. double m_scaleFactor;
  58. bool m_bSelect; //对由多个点组成的图形,点击被选中的标志
  59. QPointF m_ptPress, m_ptMove;
  60. protected:
  61. virtual QRectF boundingRect() const override;
  62. virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
  63. virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
  64. virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) Q_DECL_OVERRIDE;
  65. virtual void mousePressEvent(QGraphicsSceneMouseEvent* event) override;
  66. virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
  67. virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
  68. };
  69. #endif
  1. #include "MyCornerItem.h"
  2. #include <QDebug>
  3. MyCornerItem::MyCornerItem(QGraphicsItem * parent, QPointF point, CornerDirction dir, bool control)
  4. :QAbstractGraphicsShapeItem(parent)
  5. , m_point(point)
  6. ,m_Dir(dir)
  7. {
  8. setAcceptHoverEvents(true);
  9. QPixmap pixRotate = QPixmap("Resources\\icon\\rotate.png");
  10. m_RotateCursor = QCursor(pixRotate);
  11. m_scaleFactor = 1;
  12. m_bSelect = false;
  13. m_brush = QBrush(Qt::white);
  14. }
  15. void MyCornerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
  16. {
  17. Q_UNUSED(option); //这个宏是用来把不用到的参数注掉的功能
  18. Q_UNUSED(widget);
  19. m_scaleFactor = painter->matrix().m11();
  20. painter->save();
  21. QPen pen;
  22. pen.setWidth(0);
  23. pen.setStyle(Qt::SolidLine);
  24. painter->setPen(pen);
  25. painter->setBrush(m_brush);
  26. painter->setRenderHint(QPainter::Antialiasing, false); //不开反走样
  27. painter->drawEllipse(m_point, CORNER_SIZE/ m_scaleFactor, CORNER_SIZE/ m_scaleFactor);
  28. painter->restore();
  29. }
  30. bool MyCornerItem::hitTest(const QPointF & point)
  31. {
  32. //QPointF pt = mapFromScene(point);
  33. return boundingRect().contains(point);
  34. }
  35. void MyCornerItem::setState(SelectionHandleState state)
  36. {
  37. if (state == m_State)
  38. return;
  39. switch (state) {
  40. case SelectionHandleOff:
  41. hide();
  42. break;
  43. case SelectionHandleInactive:
  44. case SelectionHandleActive:
  45. show();
  46. break;
  47. }
  48. m_State = state;
  49. }
  50. void MyCornerItem::move(QPointF point)
  51. {
  52. if (point == m_point)
  53. return;
  54. //moveBy(0, 0);
  55. m_point = point;
  56. update();
  57. }
  58. void MyCornerItem::cornerTranslate(QPointF point)
  59. {
  60. QPointF local = point + boundingRect().topLeft();
  61. QRectF delta = QRectF(local, boundingRect().size());
  62. prepareGeometryChange();
  63. m_point = delta.center();
  64. update();
  65. }
  66. QRectF MyCornerItem::boundingRect() const
  67. {
  68. double centerX = m_point.x() - CORNER_SIZE * 2 / m_scaleFactor / 2;
  69. double centerY = m_point.y() - CORNER_SIZE * 2 / m_scaleFactor / 2;
  70. return QRectF(centerX, centerY, CORNER_SIZE * 2 / m_scaleFactor, CORNER_SIZE * 2 / m_scaleFactor);
  71. }
  72. void MyCornerItem::mousePressEvent(QGraphicsSceneMouseEvent * event)
  73. {
  74. if (event->button() == Qt::LeftButton)
  75. {
  76. m_ptPress = event->scenePos();
  77. m_ptMove = event->scenePos();
  78. m_bSelect = true;
  79. }
  80. }
  81. void MyCornerItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
  82. {
  83. if (event->buttons()&Qt::LeftButton)
  84. {
  85. m_ptMove = event->scenePos();
  86. QPointF pt = mapFromScene(m_ptMove) - mapFromScene(m_ptPress);
  87. m_ptPress = event->scenePos();
  88. cornerTranslate(pt);
  89. }
  90. QGraphicsItem::mouseMoveEvent(event);
  91. }
  92. void MyCornerItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
  93. {
  94. /*if (event->button() == Qt::LeftButton)
  95. {
  96. m_ptMove = event->scenePos();
  97. QPointF pt = mapFromScene(m_ptMove) - mapFromScene(m_ptPress);
  98. m_ptPress = event->scenePos();
  99. cornerTranslate(pt);
  100. }
  101. QGraphicsItem::mouseReleaseEvent(event);*/
  102. }
  103. void MyCornerItem::hoverEnterEvent(QGraphicsSceneHoverEvent * event)
  104. {
  105. switch (m_Dir)
  106. {
  107. case LeftTop:
  108. case RightBottom:
  109. setCursor(Qt::SizeFDiagCursor);
  110. break;
  111. case LeftBottom:
  112. case RightTop:
  113. setCursor(Qt::SizeBDiagCursor);
  114. break;
  115. case Top:
  116. case Bottom:
  117. setCursor(Qt::SizeVerCursor);
  118. break;
  119. case Left:
  120. case Right:
  121. setCursor(Qt::SizeHorCursor);
  122. break;
  123. case Rotation:
  124. setCursor(m_RotateCursor);
  125. break;
  126. default:
  127. setCursor(Qt::ArrowCursor);
  128. break;
  129. }
  130. m_brush = QBrush(Qt::green);
  131. update();
  132. QGraphicsItem::hoverEnterEvent(event);
  133. }
  134. void MyCornerItem::hoverLeaveEvent(QGraphicsSceneHoverEvent * event)
  135. {
  136. m_bSelect = false;
  137. m_brush = QBrush(Qt::white);
  138. update();
  139. QGraphicsItem::hoverLeaveEvent(event);
  140. }

2、图形基类及工厂

图形基类继承QGraphicsItem,以组合的方式声明边缘点QList<MyCornerItem*> m_HandlesList,主要实现item移动,左键双击改变z值,右双击可以改变颜色

  1. #ifndef MY_CUSTOMDRAWITEM_H
  2. #define MY_CUSTOMDRAWITEM_H
  3. #include <QGraphicsItem>
  4. #include "MyCornerItem.h"
  5. #include <QPainterPath>
  6. #include <QColorDialog>
  7. #include <QDebug>
  8. /* 需要使用的定义及相关函数 */
  9. constexpr double PI = 3.1415926;
  10. template <typename T> //T 为QPointF 或QPoint
  11. double Distance(T p1, T p2)
  12. {
  13. return std::sqrt(std::pow(p1.x() - p2.x(), 2) + std::pow(p1.y() - p2.y(), 2));
  14. }
  15. class QGraphicsItem;
  16. /**图形基类**/
  17. class CustomItemBase : public QGraphicsItem
  18. {
  19. public:
  20. CustomItemBase(QGraphicsItem *parent = nullptr)
  21. {
  22. setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
  23. this->setAcceptHoverEvents(true);
  24. m_bUseDoubleClick = true;
  25. m_brush = QBrush(QColor(0, 0, 255, 100));
  26. }
  27. virtual ~CustomItemBase() {};
  28. void SetState(SelectionHandleState state);
  29. bool isCornerSelected(int &index);
  30. void itemAtImage2Move(QPointF point)
  31. {
  32. move(point);
  33. }
  34. virtual int type() const = 0;
  35. virtual void move(QPointF point) = 0; //平移
  36. virtual void updateShape() = 0; //拖动corner后要更新形状
  37. virtual void updateConnerPos() = 0; //移动后更新所有corner的位置
  38. virtual QPainterPath shape() const = 0;
  39. protected:
  40. virtual QRectF boundingRect() const = 0;
  41. virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
  42. virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) = 0;
  43. virtual void mousePressEvent(QGraphicsSceneMouseEvent* event) override;
  44. virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
  45. virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
  46. virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
  47. public:
  48. QRectF m_rect; //外接矩形
  49. QList<MyCornerItem*> m_HandlesList;
  50. QPointF m_ptPress,m_ptMove;
  51. QBrush m_brush;
  52. bool m_bUseDoubleClick;
  53. };
  54. class CustomItemBaseFactory
  55. {
  56. public:
  57. virtual ~CustomItemBaseFactory() {}
  58. virtual CustomItemBase* CreateCustomItem(QVector<QPointF> vecPoint) = 0;
  59. virtual void DrawOnPaint(QPainter* painter, QVector<QPointF> vecPoint) = 0;
  60. virtual int NeedClickCount()
  61. { return --m_nClickCnt; } //图形需要几步完成
  62. int m_nClickCnt;
  63. inline int GetNeedCnt() { return m_nNeedCnt; }
  64. protected:
  65. int m_nNeedCnt; //不变
  66. };
  1. #include "MyCustomDrawItem.h"
  2. #include <QGraphicsScene>
  3. #include <QDebug>
  4. /************************************************************************/
  5. /* 图形基类相关函数 */
  6. /* 左双击改变Z值,右双击改变颜色 */
  7. /************************************************************************/
  8. void CustomItemBase::SetState(SelectionHandleState state)
  9. {
  10. for (auto item: m_HandlesList)
  11. item->setState(state);
  12. }
  13. bool CustomItemBase::isCornerSelected(int & index)
  14. {
  15. bool bSelect = false;
  16. index = 0;
  17. for (auto item : m_HandlesList)
  18. {
  19. if (item->getSelectState())
  20. {
  21. bSelect = true;
  22. break;
  23. }
  24. index++;
  25. }
  26. return bSelect;
  27. }
  28. QVariant CustomItemBase::itemChange(GraphicsItemChange change, const QVariant & value)
  29. {
  30. if (change == QGraphicsItem::ItemSelectedHasChanged)
  31. {
  32. qDebug() << "Item Selected:" << value.toString();
  33. SetState(value.toBool() ? SelectionHandleActive : SelectionHandleOff);
  34. }
  35. else if (change == QGraphicsItem::ItemRotationHasChanged)
  36. {
  37. qDebug() << "Item Rotation Changed:" << value.toString();
  38. }
  39. else if (change == QGraphicsItem::ItemTransformOriginPointHasChanged)
  40. {
  41. qDebug() << "ItemTransformOriginPointHasChanged:" << value.toPointF();
  42. }
  43. return QGraphicsItem::itemChange(change, value);
  44. }
  45. void CustomItemBase::mousePressEvent(QGraphicsSceneMouseEvent * event)
  46. {
  47. if (event->button() == Qt::LeftButton)
  48. {
  49. m_ptPress = event->scenePos();
  50. m_ptMove = event->scenePos();
  51. for (auto corner:m_HandlesList)
  52. {
  53. corner->setZValue(this->zValue());
  54. }
  55. }
  56. QGraphicsItem::mousePressEvent(event);
  57. }
  58. void CustomItemBase::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
  59. {
  60. if (event->buttons() & Qt::LeftButton)
  61. {
  62. int index = 0;
  63. if (!isCornerSelected(index))
  64. {
  65. m_ptMove = event->scenePos();
  66. QPointF pt = mapFromScene(m_ptMove) - mapFromScene(m_ptPress);
  67. m_ptPress = event->scenePos();
  68. move(pt);
  69. }
  70. update();
  71. }
  72. }
  73. void CustomItemBase::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
  74. {
  75. if (event->button() == Qt::LeftButton)
  76. {
  77. for (auto item : m_HandlesList)
  78. {
  79. item->setSelectState(false);
  80. }
  81. QGraphicsItem::mouseReleaseEvent(event);
  82. }
  83. }
  84. void CustomItemBase::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * event)
  85. {
  86. if (event->button() == Qt::RightButton)
  87. {
  88. if (m_bUseDoubleClick)
  89. {
  90. QColorDialog dlg;
  91. if (dlg.exec() == QDialog::Accepted)
  92. {
  93. QColor color = dlg.selectedColor();
  94. color.setAlpha(100);
  95. m_brush = QBrush(color);
  96. }
  97. }
  98. }
  99. }

至于为什么还要加个“工厂”,主要就是要加入一个图形,如果以switch的方式分别new出相关的类,这样不便于后续添加其他图形,使用工厂模式就解决了该问题。图形有自己的工厂,使用的时候只要传入相应的工厂指针就好了【不知道该模式的话自行补】。下面仅展示正矩形和圆的实现:

  1. /**************矩形******************/
  2. class CustomRectItem :public CustomItemBase
  3. {
  4. public:
  5. CustomRectItem(QRectF &rect, QGraphicsItem *parent = nullptr);
  6. virtual int type() const { return TypeRect; }
  7. virtual void move(QPointF point);
  8. virtual void updateShape(); //一个corner改变则进行一次更新
  9. virtual void updateConnerPos();
  10. virtual QPainterPath shape() const;
  11. protected:
  12. virtual QRectF boundingRect() const;
  13. virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
  14. };
  15. class CustomRectItemFactory : public CustomItemBaseFactory
  16. {
  17. public:
  18. CustomRectItemFactory()
  19. {
  20. m_nClickCnt = 1;
  21. m_nNeedCnt = 1;
  22. }
  23. virtual CustomItemBase* CreateCustomItem(QVector<QPointF> vecPoint)
  24. {
  25. return new CustomRectItem(QRectF(vecPoint.at(0), vecPoint.at(1)));
  26. }
  27. virtual void DrawOnPaint(QPainter* painter, QVector<QPointF> vecPoint)
  28. {
  29. painter->drawRect(QRectF(vecPoint.at(0), vecPoint.at(1)));
  30. }
  31. };
  32. /**************圆**************/
  33. class CustomCircleItem :public CustomItemBase
  34. {
  35. public:
  36. CustomCircleItem(QPointF center, double radius, QGraphicsItem *parent = nullptr);
  37. virtual int type() const { return TypeCircle; }
  38. virtual void move(QPointF point); //平移
  39. virtual void updateShape();
  40. virtual void updateConnerPos(); //移动后更新所有corner的位置
  41. virtual QPainterPath shape() const;
  42. protected:
  43. virtual QRectF boundingRect() const;
  44. virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
  45. };
  46. class CustomCircleItemFactory : public CustomItemBaseFactory
  47. {
  48. public:
  49. CustomCircleItemFactory()
  50. {
  51. m_nClickCnt = 1;
  52. m_nNeedCnt = 1;
  53. }
  54. virtual CustomItemBase* CreateCustomItem(QVector<QPointF> vecPoint)
  55. {
  56. double dRadius = Distance(vecPoint.at(0), vecPoint.at(1));
  57. return new CustomCircleItem(vecPoint.at(0), dRadius);
  58. }
  59. virtual void DrawOnPaint(QPainter* painter, QVector<QPointF> vecPoint)
  60. {
  61. double radius = Distance(vecPoint.at(0), vecPoint.at(1));
  62. painter->drawEllipse(vecPoint.at(0), radius, radius);
  63. }
  64. };
  1. /************************************************************************/
  2. /* 图形子类函数实现 */
  3. /* 1、 正矩形 */
  4. /************************************************************************/
  5. CustomRectItem::CustomRectItem(QRectF & rect, QGraphicsItem * parent)
  6. {
  7. m_rect = rect;
  8. m_HandlesList.clear();
  9. const int num = 8;
  10. QPointF point[num] = { QPointF((rect.left() + rect.right()) / 2,rect.bottom()),QPointF(rect.left(),rect.bottom()),
  11. QPointF(rect.left(),(rect.top() + rect.bottom()) / 2) ,QPointF(rect.left(),rect.top()),
  12. QPointF((rect.left() + rect.right()) / 2,rect.top()),QPointF(rect.right(),rect.top()),
  13. QPointF(rect.right(),(rect.top() + rect.bottom()) / 2),QPointF(rect.right(),rect.bottom())};
  14. CornerDirction dir[num] = { Bottom,LeftBottom ,Left,LeftTop ,Top , RightTop, Right,RightBottom };
  15. for (int i = 0; i < num; i++)
  16. {
  17. MyCornerItem* corner = new MyCornerItem(this, point[i], dir[i]);
  18. m_HandlesList.push_back(corner);
  19. }
  20. }
  21. void CustomRectItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
  22. {
  23. Q_UNUSED(option);
  24. Q_UNUSED(widget);
  25. QPen pen = painter->pen();
  26. pen.setWidth(0);
  27. pen.setColor(QColor(0, 255, 255, 100));
  28. painter->setPen(pen);
  29. painter->setBrush(m_brush);
  30. updateShape();
  31. painter->drawRect(m_rect);
  32. }
  33. void CustomRectItem::updateShape()
  34. {
  35. int index = 0;
  36. if (isCornerSelected(index))
  37. {
  38. QRectF rect = m_rect;
  39. CornerDirction dir = m_HandlesList[index]->getDir();
  40. switch (dir)
  41. {
  42. case Top:
  43. rect.setTop(m_HandlesList[index]->getPointCenter().y());
  44. break;
  45. case Right:
  46. rect.setRight(m_HandlesList[index]->getPointCenter().x());
  47. break;
  48. case Bottom:
  49. rect.setBottom(m_HandlesList[index]->getPointCenter().y());
  50. break;
  51. case Left:
  52. rect.setLeft(m_HandlesList[index]->getPointCenter().x());
  53. break;
  54. case LeftTop:
  55. rect.setTopLeft(m_HandlesList[index]->getPointCenter());
  56. break;
  57. case LeftBottom:
  58. rect.setBottomLeft(m_HandlesList[index]->getPointCenter());
  59. break;
  60. case RightTop:
  61. rect.setTopRight(m_HandlesList[index]->getPointCenter());
  62. break;
  63. case RightBottom:
  64. rect.setBottomRight(m_HandlesList[index]->getPointCenter());
  65. break;
  66. default:
  67. break;
  68. }
  69. prepareGeometryChange();
  70. m_rect = rect;
  71. updateConnerPos();
  72. }
  73. }
  74. QPainterPath CustomRectItem::shape() const
  75. {
  76. QPainterPath path;
  77. path.addRect(boundingRect());
  78. return path;
  79. }
  80. void CustomRectItem::move(QPointF point)
  81. {
  82. QPointF local = point + m_rect.topLeft();
  83. QRectF delta = QRectF(local, m_rect.size());
  84. prepareGeometryChange();
  85. m_rect = delta;
  86. updateConnerPos();
  87. }
  88. void CustomRectItem::updateConnerPos()
  89. {
  90. const QRectF rect = m_rect;
  91. for (auto item : m_HandlesList)
  92. {
  93. CornerDirction dir = item->getDir();
  94. switch (dir)
  95. {
  96. case Top:
  97. item->move((rect.topLeft()+rect.topRight())/2);
  98. break;
  99. case Right:
  100. item->move((rect.topRight()+ rect.bottomRight())/2);
  101. break;
  102. case Bottom:
  103. item->move((rect.bottomLeft()+ rect.bottomRight())/2);
  104. break;
  105. case Left:
  106. item->move((rect.topLeft()+ rect.bottomLeft())/2);
  107. break;
  108. case LeftTop:
  109. item->move(rect.topLeft());
  110. break;
  111. case LeftBottom:
  112. item->move(rect.bottomLeft());
  113. break;
  114. case RightTop:
  115. item->move(rect.topRight());
  116. break;
  117. case RightBottom:
  118. item->move(rect.bottomRight());
  119. break;
  120. }
  121. }
  122. }
  123. QRectF CustomRectItem::boundingRect() const
  124. {
  125. return m_rect;
  126. }

圆形实现也类似,只要理解了正矩形,圆形也一样。

因为所有的图形类都是在图像上画的,所以在图像Item中声明CustomItemBaseFactory* m_itemFactory;  使用的话就简单贴下代码 [具体请看下载链接的代码]:

m_rectFactory = new CustomRectItemFactory;

m_Scene->m_ImageItem->m_itemFactory = m_rectFactory;

总结

因为只是练习的demo,所以在完成正矩形,旋转矩形和圆形这三个图像就不在继续了,这里只是做个Mark,后面想继续在继续完善。

下载链接地址:

QtAppTest220104.zip-C/C++文档类资源-CSDN下载

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/91725
推荐阅读
相关标签
  

闽ICP备14008679号