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.

153 line
4.8 KiB

  1. #include "mygraphicsview.h"
  2. #include <QMimeData>
  3. #include <QCursor>
  4. #include <QGraphicsScene>
  5. #include <QDebug>
  6. MyGraphicsView::MyGraphicsView(QWidget *parent)
  7. : QGraphicsView(parent)
  8. {
  9. setAcceptDrops(true);
  10. viewport()->setAcceptDrops(true);
  11. setRenderHint(QPainter::Antialiasing);
  12. setFocusPolicy(Qt::StrongFocus);
  13. }
  14. void MyGraphicsView::dragEnterEvent(QDragEnterEvent *event)
  15. {
  16. if (event->mimeData()->hasFormat("application/x-component"))
  17. event->acceptProposedAction();
  18. else
  19. event->ignore();
  20. }
  21. void MyGraphicsView::dragMoveEvent(QDragMoveEvent *event)
  22. {
  23. if (event->mimeData()->hasFormat("application/x-component"))
  24. event->acceptProposedAction();
  25. else
  26. event->ignore();
  27. }
  28. void MyGraphicsView::dropEvent(QDropEvent *event)
  29. {
  30. if (!event->mimeData()->hasFormat("application/x-component")) {
  31. event->ignore();
  32. return;
  33. }
  34. QString type = QString::fromUtf8(event->mimeData()->data("application/x-component"));
  35. QPointF scenePos = mapToScene(event->pos());
  36. Item *item = new Item(type);
  37. item->setPos(scenePos);
  38. if (scene())
  39. scene()->addItem(item);
  40. event->acceptProposedAction();
  41. }
  42. void MyGraphicsView::keyPressEvent(QKeyEvent *event)
  43. {
  44. if (event->key() == Qt::Key_Delete && scene()) {
  45. QList<QGraphicsItem*> selectedItems = scene()->selectedItems();
  46. for (QGraphicsItem* item : selectedItems) {
  47. // 如果是Item,顺便删除其连线
  48. if (auto node = dynamic_cast<Item*>(item)) {
  49. QList<Connection*> conns = node->connections();
  50. for (Connection* conn : conns) {
  51. scene()->removeItem(conn);
  52. conn->from_->removeConnection(conn);
  53. conn->to_->removeConnection(conn);
  54. delete conn;
  55. }
  56. }
  57. scene()->removeItem(item);
  58. delete item;
  59. }
  60. } else {
  61. QGraphicsView::keyPressEvent(event);
  62. }
  63. }
  64. // ----------- 连线交互 ------------
  65. Item* MyGraphicsView::anchorItemAt(const QPoint& viewPos, Item::AnchorType& anchorType)
  66. {
  67. QPointF scenePos = mapToScene(viewPos);
  68. for (QGraphicsItem* item : scene()->items(scenePos)) {
  69. if (Item* node = dynamic_cast<Item*>(item)) {
  70. QRectF r = node->boundingRect();
  71. QPointF local = node->mapFromScene(scenePos);
  72. if (QLineF(local, QPointF(r.left(), r.center().y())).length() < 10) {
  73. anchorType = Item::Left;
  74. return node;
  75. }
  76. if (QLineF(local, QPointF(r.right(), r.center().y())).length() < 10) {
  77. anchorType = Item::Right;
  78. return node;
  79. }
  80. }
  81. }
  82. return nullptr;
  83. }
  84. void MyGraphicsView::mousePressEvent(QMouseEvent *event)
  85. {
  86. if (event->button() == Qt::LeftButton) {
  87. Item::AnchorType anchor;
  88. Item* node = anchorItemAt(event->pos(), anchor);
  89. if (node) {
  90. drawingConnection_ = true;
  91. startItem_ = node;
  92. startAnchor_ = anchor;
  93. tempLine_ = scene()->addLine(QLineF(node->anchorPos(anchor), mapToScene(event->pos())),
  94. QPen(Qt::darkGray, 2, Qt::DashLine));
  95. return;
  96. }
  97. }
  98. QGraphicsView::mousePressEvent(event);
  99. }
  100. void MyGraphicsView::mouseMoveEvent(QMouseEvent *event)
  101. {
  102. if (drawingConnection_ && tempLine_) {
  103. QLineF l = tempLine_->line();
  104. l.setP2(mapToScene(event->pos()));
  105. tempLine_->setLine(l);
  106. return;
  107. }
  108. QGraphicsView::mouseMoveEvent(event);
  109. }
  110. void MyGraphicsView::mouseReleaseEvent(QMouseEvent *event)
  111. {
  112. if (drawingConnection_ && tempLine_) {
  113. // 检查鼠标释放点是否在某个Item boundingRect内
  114. QPointF scenePos = mapToScene(event->pos());
  115. for (QGraphicsItem* item : scene()->items(scenePos)) {
  116. if (Item* node = dynamic_cast<Item*>(item)) {
  117. QRectF r = node->boundingRect();
  118. QPointF local = node->mapFromScene(scenePos);
  119. // 计算落点距离左右端点
  120. double distLeft = QLineF(local, QPointF(r.left(), r.center().y())).length();
  121. double distRight = QLineF(local, QPointF(r.right(), r.center().y())).length();
  122. Item::AnchorType anchor = (distLeft < distRight) ? Item::Left : Item::Right;
  123. // 生成连线
  124. Connection* conn = new Connection(startItem_, startAnchor_, node, anchor);
  125. scene()->addItem(conn);
  126. break;
  127. }
  128. }
  129. // 清除临时线
  130. scene()->removeItem(tempLine_);
  131. delete tempLine_;
  132. tempLine_ = nullptr;
  133. drawingConnection_ = false;
  134. startItem_ = nullptr;
  135. return;
  136. }
  137. QGraphicsView::mouseReleaseEvent(event);
  138. }