WindowAppItemLinkLine.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. #include "WindowAppItemLinkLine.h"
  2. #include "WindowAppItemLink.h"
  3. WindowAppItemLinkLine::WindowAppItemLinkLine(
  4. QPointF ptStart,
  5. QPointF ptEnd,
  6. QGraphicsItemGroup* parent,
  7. LINK_MODE linkMode
  8. )
  9. : m_bLinkEndLine(false)
  10. , m_bLinkStartLine(false)
  11. , m_bIsDragging(false)
  12. , m_mode(linkMode)
  13. , m_nLineIndex(-1)
  14. {
  15. // 接收悬停事件,用于显示鼠标切换效果
  16. setAcceptHoverEvents(true);
  17. // 设置风格,可选择可拖动
  18. // setFlag(QGraphicsItem::ItemIsMovable, true);
  19. setFlag(QGraphicsItem::ItemIsSelectable, true);
  20. // 接收Item移动消息
  21. // setFlag(QGraphicsItem::ItemSendsGeometryChanges);
  22. this->setParentItem(parent);
  23. m_parentGroup = qgraphicsitem_cast<WindowAppItemLink*>(parent);
  24. this->setLine(QLineF(ptStart, ptEnd));
  25. // 设置画笔
  26. setPen(QPen(COLOR_INF_LINE, PEN_LINE_WIDTH, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
  27. }
  28. /// <summary>
  29. /// 更新连线位置
  30. /// </summary>
  31. /// <param name="ptStart"></param>
  32. /// <param name="ptEnd"></param>
  33. void WindowAppItemLinkLine::updateLine(QPointF ptStart, QPointF ptEnd)
  34. {
  35. this->setLine(QLineF(ptStart, ptEnd));
  36. }
  37. /// <summary>
  38. /// 更新线段的起点坐标
  39. /// </summary>
  40. /// <param name="pt"></param>
  41. void WindowAppItemLinkLine::setP1(const QPointF pt)
  42. {
  43. QLineF ajustLine = this->line();
  44. ajustLine.setP1(pt);
  45. this->setLine(ajustLine);
  46. }
  47. /// <summary>
  48. /// 更新线段的终点坐标
  49. /// </summary>
  50. /// <param name="pt"></param>
  51. void WindowAppItemLinkLine::setP2(const QPointF pt)
  52. {
  53. QLineF ajustLine = this->line();
  54. ajustLine.setP2(pt);
  55. this->setLine(ajustLine);
  56. }
  57. /// <summary>
  58. /// 返回边界区域
  59. /// </summary>
  60. /// <returns></returns>
  61. QRectF WindowAppItemLinkLine::boundingRect() const
  62. {
  63. qreal extra = (pen().width()) * 4.0;
  64. QRectF rc = QRectF(
  65. line().p1(),
  66. QSizeF(line().p2().x() - line().p1().x(),
  67. line().p2().y() - line().p1().y()
  68. ))
  69. .normalized()
  70. .adjusted(-extra, -extra, extra, extra);
  71. return rc;
  72. }
  73. /// <summary>
  74. /// 形状边界(为了扩大线条的可点击范围)
  75. /// </summary>
  76. /// <returns></returns>
  77. QPainterPath WindowAppItemLinkLine::shape() const
  78. {
  79. QPainterPath path = QGraphicsLineItem::shape();
  80. qreal extra = (pen().width()) * 4.0;
  81. extra *= 1.414;
  82. path = QGraphicsLineItem::shape();
  83. // 通过Stroker设置精确Shape
  84. QPainterPathStroker stroker;
  85. stroker.setWidth(extra);
  86. path = stroker.createStroke(path);
  87. return path;
  88. }
  89. /// <summary>
  90. /// 绘制线条
  91. /// </summary>
  92. /// <param name="painter"></param>
  93. /// <param name="option"></param>
  94. /// <param name="widget"></param>
  95. void WindowAppItemLinkLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget /*= nullptr*/)
  96. {
  97. Q_UNUSED(option);
  98. Q_UNUSED(widget);
  99. painter->setRenderHint(QPainter::Antialiasing, true);
  100. painter->save();
  101. // 如果父类的选中状态发生了变更的话
  102. if (this->parentItem()->isSelected())
  103. {
  104. painter->setPen(QPen(COLOR_INF_LINE, PEN_LINE_WIDTH_SEL, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
  105. }
  106. else
  107. {
  108. painter->setPen(QPen(COLOR_INF_LINE, PEN_LINE_WIDTH, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
  109. }
  110. // 绘制线条
  111. painter->drawLine(line());
  112. // 如果是终点连接线,需要绘制箭头
  113. if (this->m_bLinkEndLine)
  114. {
  115. double angle = atan2(line().dy(), -line().dx());
  116. QPointF arrowP1 = line().p2() + QPointF(sin(angle + M_PI / 3) * LINE_ARROW_SIZE,
  117. cos(angle + M_PI / 3) * LINE_ARROW_SIZE);
  118. QPointF arrowP2 = line().p2() + QPointF(sin(angle + M_PI - M_PI / 3) * LINE_ARROW_SIZE,
  119. cos(angle + M_PI - M_PI / 3) * LINE_ARROW_SIZE);
  120. painter->drawLine(line().p2(), arrowP1);
  121. painter->drawLine(line().p2(), arrowP2);
  122. }
  123. painter->restore();
  124. }
  125. /// <summary>
  126. /// 跳过Group,自行处理部分消息
  127. /// </summary>
  128. /// <param name="event"></param>
  129. /// <returns></returns>
  130. bool WindowAppItemLinkLine::sceneEvent(QEvent* event)
  131. {
  132. switch (event->type())
  133. {
  134. // 处理鼠标Hover消息,很奇怪不知道为什么在Group中无法触发这个消息,只能放到子线段中了
  135. case QEvent::GraphicsSceneHoverEnter:
  136. hoverEnterEvent(static_cast<QGraphicsSceneHoverEvent*>(event));
  137. break;
  138. case QEvent::GraphicsSceneMousePress:
  139. mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(event));
  140. break;
  141. case QEvent::GraphicsSceneMouseMove:
  142. mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(event));
  143. break;
  144. case QEvent::GraphicsSceneMouseRelease:
  145. mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(event));
  146. break;
  147. }
  148. event->accept();
  149. return QGraphicsLineItem::sceneEvent(event);
  150. }
  151. ///// <summary>
  152. ///// 鼠标悬浮事件(用于显示移动用的鼠标)
  153. ///// </summary>
  154. ///// <param name="event"></param>
  155. //void WindowAppItemLinkLine::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
  156. //{
  157. // // 如果控件处于选中状态,则根据鼠标位置显示拉伸鼠标
  158. // if (this->isSelected())
  159. // {
  160. // //setCursor(Qt::SizeVerCursor);
  161. // // setCursor(Qt::SizeHorCursor);
  162. // }
  163. //
  164. // qDebug() << "WindowAppItemLinkLine::hoverMoveEvent";
  165. //
  166. // QGraphicsLineItem::hoverMoveEvent(event);
  167. //}
  168. //=============================================================================
  169. //
  170. // 线条拖动相关代码
  171. //
  172. //=============================================================================
  173. /// <summary>
  174. /// 鼠标进入悬浮事件(用于显示拖动用的鼠标)
  175. /// </summary>
  176. /// <param name="event"></param>
  177. void WindowAppItemLinkLine::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
  178. {
  179. // qDebug() << "WindowAppItemLinkLine::hoverEnterEvent";
  180. // 如果不支持拖拽,则干脆不能改变鼠标样式
  181. if (!isSupportDrag())
  182. {
  183. return;
  184. }
  185. // 根据是水平线还是垂直线显示不同的鼠标
  186. if (isVertical())
  187. {
  188. setCursor(Qt::SizeHorCursor);
  189. }
  190. else if(isHorizontal())
  191. {
  192. setCursor(Qt::SizeVerCursor);
  193. }
  194. // Error
  195. else
  196. {
  197. }
  198. QGraphicsLineItem::hoverEnterEvent(event);
  199. }
  200. /// <summary>
  201. /// 鼠标按下事件(用于触发Link移动)
  202. /// </summary>
  203. /// <param name="event"></param>
  204. void WindowAppItemLinkLine::mousePressEvent(QGraphicsSceneMouseEvent* event)
  205. {
  206. // qDebug() << "WindowAppItemLinkLine::mousePressEvent";
  207. // QPointF mousePoint = event->pos();
  208. if (!this->isSupportDrag())
  209. {
  210. return;
  211. }
  212. m_bIsDragging = true;
  213. QGraphicsLineItem::mousePressEvent(event);
  214. }
  215. /// <summary>
  216. /// 鼠标移动事件(用于移动Link)
  217. /// </summary>
  218. /// <param name="event"></param>
  219. void WindowAppItemLinkLine::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
  220. {
  221. // qDebug() << "WindowAppItemLinkLine::mouseMoveEvent";
  222. QPointF mousePoint = event->pos();
  223. if (!m_bIsDragging)
  224. {
  225. return;
  226. }
  227. QPointF lineP1 = this->line().p1();
  228. QPointF lineP2 = this->line().p2();
  229. // 水平线移动
  230. if (isVertical())
  231. {
  232. lineP1.setX(mousePoint.x());
  233. lineP2.setX(mousePoint.x());
  234. // 交给Group检查一下本次移动是否可行
  235. if (m_parentGroup->canMove(lineP1, lineP2))
  236. {
  237. this->setLine(QLineF(lineP1, lineP2));
  238. // 发送线段移动信号,用于在Group中同步移动其他线段
  239. emit lineMoveSignal(this);
  240. }
  241. }
  242. // 垂直线移动
  243. else if(isHorizontal())
  244. {
  245. lineP1.setY(mousePoint.y());
  246. lineP2.setY(mousePoint.y());
  247. // 交给Group检查一下本次移动是否可行
  248. if (m_parentGroup->canMove(lineP1, lineP2))
  249. {
  250. this->setLine(QLineF(lineP1, lineP2));
  251. // 发送线段移动信号,用于在Group中同步移动其他线段
  252. emit lineMoveSignal(this);
  253. }
  254. }
  255. // Error
  256. else
  257. {
  258. }
  259. QGraphicsLineItem::mouseMoveEvent(event);
  260. }
  261. /// <summary>
  262. /// 鼠标释放事件(用于鼠标还原以及接收拉伸状态)
  263. /// </summary>
  264. /// <param name="event"></param>
  265. void WindowAppItemLinkLine::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
  266. {
  267. // qDebug() << "WindowAppItemLinkLine::mouseReleaseEvent";
  268. // 还原鼠标
  269. // setCursor(Qt::ArrowCursor);
  270. m_bIsDragging = false;
  271. QGraphicsLineItem::mouseReleaseEvent(event);
  272. }
  273. /// <summary>
  274. /// 是否是垂直线条
  275. /// </summary>
  276. /// <returns></returns>
  277. bool WindowAppItemLinkLine::isVertical()
  278. {
  279. QLine seg = this->line().toLine();
  280. return (seg.x1() == seg.x2());
  281. }
  282. /// <summary>
  283. /// 是否是水平线条
  284. /// </summary>
  285. /// <returns></returns>
  286. bool WindowAppItemLinkLine::isHorizontal()
  287. {
  288. QLine seg = this->line().toLine();
  289. return (seg.y1() == seg.y2());
  290. }
  291. /// <summary>
  292. /// 本线段是否支持拖拽
  293. /// </summary>
  294. /// <returns></returns>
  295. bool WindowAppItemLinkLine::isSupportDrag()
  296. {
  297. // 如果终点连线,则不支持拖拽功能
  298. if (m_bLinkEndLine)
  299. {
  300. return false;
  301. }
  302. // 如果是普通模式下的起点连线,也不支持拖拽功能
  303. if (m_bLinkStartLine && m_mode == LINK_MODE::LINK_NORMAL)
  304. {
  305. return false;
  306. }
  307. return true;
  308. }