综合平台编辑器
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.

147 lines
4.0 KiB

  1. #include "customgraphicsscene.h"
  2. #include <QGraphicsSceneMouseEvent>
  3. #include <QGraphicsView>
  4. #include <QKeyEvent>
  5. #include <QGuiApplication>
  6. #include <QMenu>
  7. // 实现新的构造函数
  8. CustomGraphicsScene::CustomGraphicsScene(QGraphicsView* view, QObject *parent)
  9. : QGraphicsScene(parent), m_mode(Normal), m_view(view)
  10. {
  11. // 断言确保传入的 view 是有效的
  12. Q_ASSERT(m_view);
  13. }
  14. void CustomGraphicsScene::setMode(Mode mode)
  15. {
  16. if (m_mode == mode) return;
  17. m_mode = mode;
  18. // 根据模式设置光标
  19. if (m_mode == CreateItem) {
  20. m_view->setCursor(Qt::CrossCursor);
  21. } else {
  22. m_view->setCursor(Qt::ArrowCursor); // 恢复为标准箭头光标
  23. }
  24. }
  25. void CustomGraphicsScene::setComponentTypeToCreate(ComponentType type)
  26. {
  27. m_componentTypeToCreate = type;
  28. }
  29. void CustomGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
  30. {
  31. if (mouseEvent->button() != Qt::LeftButton) {
  32. QGraphicsScene::mousePressEvent(mouseEvent);
  33. return;
  34. }
  35. if (m_mode == CreateItem) {
  36. HmiComponent* item = nullptr;
  37. switch (m_componentTypeToCreate) {
  38. case ComponentType::Button:
  39. item = new HmiButton();
  40. break;
  41. case ComponentType::Indicator:
  42. item = new HmiIndicator();
  43. break;
  44. }
  45. if (item)
  46. {
  47. item->setPos(mouseEvent->scenePos());
  48. if (item->scene() == nullptr)
  49. {
  50. addItem(item);
  51. emit componentCreated(item);
  52. }
  53. else
  54. {
  55. // 如果 item 已经被添加到场景中,则删除它,避免内存泄漏
  56. delete item;
  57. }
  58. }
  59. setMode(Normal);
  60. }
  61. else
  62. {
  63. QGraphicsScene::mousePressEvent(mouseEvent);
  64. }
  65. }
  66. void CustomGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
  67. {
  68. QGraphicsScene::mouseMoveEvent(mouseEvent);
  69. }
  70. void CustomGraphicsScene::keyPressEvent(QKeyEvent *keyEvent)
  71. {
  72. // 退出创建模式
  73. if (keyEvent->key() == Qt::Key_Escape && m_mode == CreateItem) {
  74. setMode(Normal);
  75. keyEvent->accept();
  76. return;
  77. }
  78. // 处理删除、复制、粘贴
  79. if (selectedItems().isEmpty()) {
  80. QGraphicsScene::keyPressEvent(keyEvent);
  81. return;
  82. }
  83. switch (keyEvent->key()) {
  84. case Qt::Key_Delete:
  85. emit deleteRequestFromScene();
  86. keyEvent->accept();
  87. break;
  88. case Qt::Key_C:
  89. if (keyEvent->modifiers() & Qt::ControlModifier) {
  90. emit copyRequestFromScene();
  91. keyEvent->accept();
  92. }
  93. break;
  94. case Qt::Key_V:
  95. if (keyEvent->modifiers() & Qt::ControlModifier) {
  96. // 使用与 contextMenuEvent 相同的方式获取粘贴位置
  97. QPointF pastePos = views().first()->mapToScene(views().first()->viewport()->mapFromGlobal(QCursor::pos()));
  98. emit pasteRequestFromScene(pastePos);
  99. keyEvent->accept();
  100. }
  101. break;
  102. default:
  103. break;
  104. }
  105. QGraphicsScene::keyPressEvent(keyEvent);
  106. }
  107. void CustomGraphicsScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *contextMenuEvent)
  108. {
  109. // 检查鼠标下方是否有图形项
  110. QGraphicsItem *item = itemAt(contextMenuEvent->scenePos(), views().first()->transform());
  111. if (!item) {
  112. // 如果点击在空白处,则显示我们的粘贴菜单
  113. contextMenuEvent->accept();
  114. QMenu menu;
  115. QAction *pasteAction = menu.addAction("粘贴");
  116. // 将菜单动作连接到场景的粘贴请求信号
  117. connect(pasteAction, &QAction::triggered, this, [this, contextMenuEvent]() {
  118. emit pasteRequestFromScene(contextMenuEvent->scenePos());
  119. });
  120. menu.exec(contextMenuEvent->screenPos());
  121. } else {
  122. // 如果点击在图形项上,则将事件传递给该图形项处理(这会调用 HmiComponent::contextMenuEvent)
  123. QGraphicsScene::contextMenuEvent(contextMenuEvent);
  124. }
  125. }