You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
5.3 KiB

  1. #ifndef GRAPHICSITEMS_H
  2. #define GRAPHICSITEMS_H
  3. #include <QGraphicsRectItem>
  4. #include <QGraphicsEllipseItem>
  5. #include <QGraphicsSceneHoverEvent>
  6. #include <QGraphicsSceneMouseEvent>
  7. #include <QPainter>
  8. #include <QString>
  9. #include <QColor>
  10. #include <QCursor>
  11. #include <QGraphicsScene>
  12. // 命名项接口(用于属性设置)
  13. class NamedItem
  14. {
  15. public:
  16. virtual QString name() const = 0;
  17. virtual void setName(const QString &name) = 0;
  18. virtual ~NamedItem() = default;
  19. };
  20. // 可调整大小的图形基类(模板)
  21. template <typename BaseShape>
  22. class ResizableShape : public BaseShape, public NamedItem
  23. {
  24. protected:
  25. bool m_resizing;
  26. QString m_name;
  27. QPointF m_initialPos; // 用于存储调整开始时的位置
  28. // 获取右下角调整区域
  29. QRectF getResizeArea() const
  30. {
  31. QRectF r = this->rect();
  32. return QRectF(r.bottomRight() - QPointF(20, 20), r.bottomRight());
  33. }
  34. // 检测是否在右下角调整区域
  35. bool isInResizeArea(const QPointF &pos) const
  36. {
  37. return getResizeArea().contains(pos);
  38. }
  39. public:
  40. ResizableShape(qreal x, qreal y, qreal w, qreal h)
  41. : BaseShape(x, y, w, h), m_resizing(false)
  42. {
  43. this->setFlag(QGraphicsItem::ItemIsMovable, true);
  44. this->setFlag(QGraphicsItem::ItemIsSelectable, true);
  45. this->setAcceptHoverEvents(true);
  46. this->setCursor(Qt::SizeAllCursor); // 默认光标为移动光标
  47. }
  48. // 事件处理(调整大小逻辑)
  49. void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override
  50. {
  51. if (isInResizeArea(event->pos())) {
  52. this->setCursor(Qt::SizeFDiagCursor); // 右下角显示缩放光标
  53. } else {
  54. this->setCursor(Qt::SizeAllCursor); // 其他区域显示移动光标
  55. }
  56. BaseShape::hoverMoveEvent(event);
  57. }
  58. void mousePressEvent(QGraphicsSceneMouseEvent *event) override
  59. {
  60. if (isInResizeArea(event->pos())) {
  61. m_resizing = true;
  62. m_initialPos = event->pos(); // 存储初始位置
  63. this->setCursor(Qt::SizeFDiagCursor);
  64. }
  65. else
  66. {
  67. m_resizing = false;
  68. BaseShape::mousePressEvent(event);
  69. }
  70. }
  71. void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
  72. {
  73. if (m_resizing) {
  74. // 计算尺寸变化量
  75. QPointF delta = event->pos() - m_initialPos;
  76. QRectF newRect = this->rect();
  77. // 保持左上角不变,调整右下角
  78. newRect.setWidth(newRect.width() + delta.x());
  79. newRect.setHeight(newRect.height() + delta.y());
  80. // 设置最小尺寸
  81. if (newRect.width() < 20) newRect.setWidth(20);
  82. if (newRect.height() < 20) newRect.setHeight(20);
  83. this->setRect(newRect);
  84. this->update();
  85. m_initialPos = event->pos(); // 更新初始位置
  86. } else {
  87. BaseShape::mouseMoveEvent(event);
  88. }
  89. }
  90. void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override
  91. {
  92. if (m_resizing) {
  93. m_resizing = false;
  94. // 根据位置恢复光标
  95. if (isInResizeArea(event->pos())) {
  96. this->setCursor(Qt::SizeFDiagCursor); // 仍在调整区域
  97. } else {
  98. this->setCursor(Qt::SizeAllCursor); // 离开调整区域
  99. }
  100. }
  101. BaseShape::mouseReleaseEvent(event);
  102. }
  103. void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
  104. {
  105. BaseShape::paint(painter, option, widget);
  106. }
  107. // 命名项接口实现
  108. QString name() const override { return m_name; }
  109. void setName(const QString &name) override { m_name = name; }
  110. };
  111. // 可调整大小的矩形(按钮)
  112. class ResizableRectangle : public ResizableShape<QGraphicsRectItem>
  113. {
  114. public:
  115. ResizableRectangle(qreal x, qreal y, qreal w, qreal h)
  116. : ResizableShape<QGraphicsRectItem>(x, y, w, h)
  117. {
  118. m_pressedColor = Qt::darkYellow;
  119. m_releasedColor = Qt::yellow;
  120. this->setBrush(m_releasedColor);
  121. }
  122. QColor pressedColor() const { return m_pressedColor; }
  123. void setPressedColor(const QColor &color) { m_pressedColor = color; }
  124. QColor releasedColor() const { return m_releasedColor; }
  125. void setReleasedColor(const QColor &color) {
  126. m_releasedColor = color;
  127. this->setBrush(m_releasedColor); // 更新显示
  128. }
  129. private:
  130. QColor m_pressedColor; // 按下颜色
  131. QColor m_releasedColor; // 释放颜色
  132. };
  133. // 可调整大小的椭圆(指示灯)
  134. class ResizableEllipse : public ResizableShape<QGraphicsEllipseItem>
  135. {
  136. public:
  137. ResizableEllipse(qreal x, qreal y, qreal w, qreal h)
  138. : ResizableShape<QGraphicsEllipseItem>(x, y, w, h)
  139. {
  140. m_onColor = Qt::green;
  141. m_offColor = Qt::red;
  142. this->setBrush(m_offColor);
  143. }
  144. QColor onColor() const { return m_onColor; }
  145. void setOnColor(const QColor &color) {
  146. m_onColor = color;
  147. this->setBrush(m_onColor); // 更新显示
  148. }
  149. QColor offColor() const { return m_offColor; }
  150. void setOffColor(const QColor &color) { m_offColor = color; }
  151. private:
  152. QColor m_onColor; // 开状态颜色
  153. QColor m_offColor; // 关状态颜色
  154. };
  155. #endif // GRAPHICSITEMS_H