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.

314 line
11 KiB

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include"hmiwidget.h"
  4. #include<QDebug>
  5. #include<QDir>
  6. #include <QGraphicsView>
  7. #include <QGraphicsScene>
  8. MainWindow::MainWindow(QWidget *parent)
  9. : QMainWindow(parent)
  10. , ui(new Ui::MainWindow)
  11. ,canDrawEllipse(false)
  12. ,canDrawRectangle(false)
  13. {
  14. ui->setupUi(this);
  15. addDockWidget(Qt::BottomDockWidgetArea, ui->dockWidget_3);//将dockWidget_3添加到主窗口的下方
  16. scene = new QGraphicsScene(this);
  17. scene->setSceneRect(0, 0, 800, 600);//因为场景初始无内容时,QGraphicsView 自动将场景中心与视图中心对齐
  18. scene->setBackgroundBrush(QBrush(Qt::lightGray));
  19. ui->graphicsView_2->setScene(scene);
  20. ui->graphicsView_2->setRenderHint(QPainter::Antialiasing);
  21. ui->graphicsView_2->setDragMode(QGraphicsView::RubberBandDrag);
  22. ui->graphicsView_2->setAcceptDrops(true);// 启用视图的拖放功能(接收拖拽)
  23. ui->graphicsView_2->viewport()->installEventFilter(this);
  24. ui->treeWidget_2->setDragEnabled(true);// 允许拖拽
  25. ui->treeWidget_2->setDragDropMode(QAbstractItemView::DragOnly);// 仅拖拽
  26. ui->actiondelete->setShortcut(QKeySequence::Delete);//设置快捷键
  27. ui->actioncopy->setShortcut(QKeySequence::Copy);
  28. ui->actionpaste->setShortcut(QKeySequence::Paste);
  29. ui->treeWidget->topLevelItem(0)->setIcon(0, QIcon("../two/IntegratedPlatform/images/T-常开触点-01.png"));
  30. ui->treeWidget->topLevelItem(1)->setIcon(0, QIcon("../two/IntegratedPlatform/images/T-常闭触点-01-01.png"));
  31. ui->treeWidget->topLevelItem(2)->setIcon(0, QIcon("../two/IntegratedPlatform/images/大于等于.png"));
  32. ui->treeWidget->topLevelItem(3)->setIcon(0, QIcon("../two/IntegratedPlatform/images/线-圈-圈.png"));
  33. ui->treeWidget_2->topLevelItem(0)->setIcon(0, QIcon("../two/IntegratedPlatform/images/灯泡.png"));
  34. ui->treeWidget_2->topLevelItem(1)->setIcon(0, QIcon("../two/IntegratedPlatform/images/按钮.png"));
  35. connect(ui->treeWidget_2, &QTreeWidget::itemClicked, this, &MainWindow::onHmiItemClicked);
  36. connect(ui->actiondelete, &QAction::triggered, this, &MainWindow::onActionDeleteTriggered);
  37. connect(ui->actioncopy, &QAction::triggered, this, &MainWindow::onActionCopyTriggered);
  38. connect(ui->actionpaste, &QAction::triggered, this, &MainWindow::onActionPasteTriggered);
  39. }
  40. MainWindow::~MainWindow()
  41. {
  42. delete ui;
  43. }
  44. void MainWindow::onHmiItemClicked(QTreeWidgetItem *item)
  45. {
  46. if (item->text(0) == "指示灯")
  47. {
  48. canDrawEllipse = true;
  49. canDrawRectangle = false;
  50. }
  51. else if (item->text(0) == "按钮")
  52. {
  53. canDrawEllipse = false;
  54. canDrawRectangle = true;
  55. }
  56. else
  57. {
  58. canDrawEllipse = false;
  59. canDrawRectangle = false;
  60. }
  61. }
  62. bool MainWindow::eventFilter(QObject *obj, QEvent *event)
  63. {
  64. if (obj != ui->graphicsView_2->viewport())
  65. {
  66. return QMainWindow::eventFilter(obj, event);
  67. }
  68. if (event->type() == QEvent::MouseButtonPress)//点击生成
  69. {
  70. QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
  71. if (mouseEvent->button() == Qt::RightButton)//打开右键菜单
  72. {
  73. QPointF scenePos = ui->graphicsView_2->mapToScene(mouseEvent->pos());
  74. QGraphicsItem *item = scene->itemAt(scenePos, ui->graphicsView_2->transform());
  75. if (item && !item->isSelected())// 如果有项在点击位置,选中它并清除其他选择
  76. {
  77. scene->clearSelection(); // 清除所有当前选择
  78. item->setSelected(true); // 选中当前项
  79. }
  80. QPoint globalPos = mouseEvent->globalPos();
  81. showContextMenu(globalPos);
  82. return true;
  83. }
  84. if (mouseEvent->button() == Qt::LeftButton)
  85. {
  86. QPointF scenePos = ui->graphicsView_2->mapToScene(mouseEvent->pos());
  87. QGraphicsItem *item = scene->itemAt(scenePos, ui->graphicsView_2->transform());
  88. if (item)
  89. {
  90. return QMainWindow::eventFilter(obj, event);
  91. }
  92. if (canDrawEllipse)
  93. {
  94. createEllipse(scenePos); // 封装为函数,避免重复代码
  95. resetDrawFlags();
  96. }
  97. else if (canDrawRectangle)
  98. {
  99. createRectangle(scenePos); // 封装为函数
  100. resetDrawFlags();
  101. }
  102. if (!item)
  103. {
  104. scene->clearSelection();
  105. if (ui->treeWidget_2->currentItem())
  106. {
  107. ui->treeWidget_2->currentItem()->setSelected(false);
  108. }
  109. }
  110. return true;
  111. }
  112. }
  113. //拖拽生成
  114. if (event->type() == QEvent::DragEnter)
  115. {
  116. QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent*>(event);
  117. if (dragEvent->source() == ui->treeWidget_2)//检查拖拽源是否为树控件,并接受拖拽
  118. {
  119. dragEvent->acceptProposedAction();
  120. return true;
  121. }
  122. }
  123. // 拖拽移动(可选:显示拖拽反馈)
  124. if (event->type() == QEvent::DragMove)
  125. {
  126. QDragMoveEvent *dragEvent = static_cast<QDragMoveEvent*>(event);
  127. dragEvent->acceptProposedAction();
  128. return true;
  129. }
  130. // 拖拽释放(生成图形)
  131. if (event->type() == QEvent::Drop)
  132. {
  133. QDropEvent *dropEvent = static_cast<QDropEvent*>(event);
  134. QModelIndex index = ui->treeWidget_2->currentIndex();// 获取拖拽的树项
  135. if (!index.isValid()) return true;
  136. QTreeWidgetItem *item = ui->treeWidget_2->currentItem();
  137. if (!item) return true;
  138. QPointF scenePos = ui->graphicsView_2->mapToScene(dropEvent->pos());// 计算释放位置(转换为场景坐标)
  139. if (item->text(0) == "指示灯")
  140. {
  141. createEllipse(scenePos);
  142. }
  143. else if (item->text(0) == "按钮")
  144. {
  145. createRectangle(scenePos);
  146. }
  147. dropEvent->acceptProposedAction();
  148. return true;
  149. }
  150. return QMainWindow::eventFilter(obj, event);
  151. }
  152. //删除
  153. void MainWindow::onActionDeleteTriggered()
  154. {
  155. QList<QGraphicsItem*> selectedItems = scene->selectedItems();//获取场景中所有选中的项
  156. foreach (QGraphicsItem *item, selectedItems)//遍历并删除所有选中的项
  157. {
  158. scene->removeItem(item);
  159. delete item;//删除对象
  160. }
  161. }
  162. // 复制功能
  163. void MainWindow::onActionCopyTriggered()
  164. {
  165. copiedItemsData.clear();
  166. QList<QGraphicsItem*> selectedItems = scene->selectedItems();
  167. if (selectedItems.isEmpty()) return;
  168. foreach (QGraphicsItem *item, selectedItems)
  169. {
  170. QByteArray itemData;
  171. QDataStream stream(&itemData, QIODevice::WriteOnly);
  172. stream << item->type();// 基础属性
  173. stream << item->pos();
  174. stream << item->flags();
  175. stream << item->transform();
  176. stream << item->isVisible();
  177. if (auto shapeItem = dynamic_cast<QAbstractGraphicsShapeItem*>(item))//处理所有图形形状项
  178. {
  179. stream << shapeItem->pen();
  180. stream << shapeItem->brush();
  181. stream << shapeItem->boundingRect();
  182. }
  183. if (auto resizableRect = dynamic_cast<ResizableRectangle*>(item))//处理矩形圆形两项,存储几何信息
  184. {
  185. stream << resizableRect->rect();//实际存储的矩形
  186. }
  187. else if (auto resizableEllipse = dynamic_cast<ResizableEllipse*>(item))
  188. {
  189. stream << resizableEllipse->rect();
  190. }
  191. copiedItemsData.append(itemData);
  192. }
  193. lastPastePos = selectedItems.first()->pos();
  194. }
  195. // 粘贴功能
  196. void MainWindow::onActionPasteTriggered()
  197. {
  198. if (copiedItemsData.isEmpty()) return;
  199. QPointF offset(20,20);
  200. lastPastePos+=offset;
  201. scene->clearSelection();
  202. foreach (const QByteArray &itemData, copiedItemsData)
  203. {
  204. QDataStream stream(itemData);
  205. int itemType;
  206. QPointF pos;
  207. QGraphicsItem::GraphicsItemFlags flags;
  208. QTransform transform;
  209. bool visible;
  210. stream >> itemType >> pos >> flags >> transform >> visible;
  211. QGraphicsItem *newItem = nullptr;
  212. switch (itemType)
  213. {
  214. case QGraphicsRectItem::Type:
  215. {
  216. QPen pen;
  217. QBrush brush;
  218. QRectF rect;
  219. stream >> pen >> brush >> rect;
  220. ResizableRectangle *rectItem = new ResizableRectangle(rect.x(), rect.y(), rect.width(), rect.height());
  221. rectItem->setPen(pen);
  222. rectItem->setBrush(brush);
  223. newItem = rectItem;
  224. break;
  225. }
  226. case QGraphicsEllipseItem::Type:
  227. {
  228. QPen pen;
  229. QBrush brush;
  230. QRectF rect;
  231. stream >> pen >> brush >> rect;
  232. ResizableEllipse *ellipseItem = new ResizableEllipse(rect.x(), rect.y(), rect.width(), rect.height());
  233. ellipseItem->setPen(pen);
  234. ellipseItem->setBrush(brush);
  235. newItem = ellipseItem;
  236. break;
  237. }
  238. }
  239. if (newItem) {
  240. scene->addItem(newItem);
  241. newItem->setPos(lastPastePos);
  242. newItem->setFlags(flags);
  243. newItem->setTransform(transform);
  244. newItem->setVisible(visible);
  245. newItem->setSelected(true);
  246. }
  247. }
  248. }
  249. void MainWindow::createEllipse(const QPointF &pos)
  250. {
  251. ResizableEllipse *ellipse = new ResizableEllipse(pos.x(), pos.y(), 50, 50);
  252. ellipse->setBrush(QBrush(Qt::red));
  253. ellipse->setPen(QPen(Qt::black, 1));
  254. scene->addItem(ellipse);
  255. ellipse->setSelected(true);
  256. }
  257. void MainWindow::createRectangle(const QPointF &pos)
  258. {
  259. ResizableRectangle *rectangle = new ResizableRectangle(pos.x(), pos.y(), 100, 50);
  260. rectangle->setBrush(QBrush(Qt::yellow));
  261. rectangle->setPen(QPen(Qt::black, 1));
  262. scene->addItem(rectangle);
  263. rectangle->setSelected(true);
  264. }
  265. void MainWindow::resetDrawFlags()
  266. {
  267. canDrawEllipse = false;
  268. canDrawRectangle = false;
  269. if (ui->treeWidget_2->currentItem())
  270. {
  271. ui->treeWidget_2->currentItem()->setSelected(false);
  272. }
  273. }
  274. void MainWindow::showContextMenu(QPoint pos)
  275. {
  276. QPoint viewportPos = ui->graphicsView_2->mapFromGlobal(pos);
  277. QPointF scenePos = ui->graphicsView_2->mapToScene(viewportPos);
  278. QGraphicsItem* clickedItem = scene->itemAt(scenePos, ui->graphicsView_2->transform());//检查是否有图形项在点击位置
  279. QMenu contextMenu(this);
  280. if (!clickedItem)
  281. {
  282. QAction* pasteAction = contextMenu.addAction("粘贴");// 空白处右键:只添加粘贴选项
  283. pasteAction->setEnabled(!copiedItemsData.isEmpty());
  284. connect(pasteAction, &QAction::triggered, this, &MainWindow::onActionPasteTriggered);
  285. contextMenu.exec(pos+QPoint(10, 10));
  286. return;
  287. }
  288. // 添加动作
  289. QAction* propertiesAction = contextMenu.addAction("属性");
  290. QAction* copyAction = contextMenu.addAction("复制");
  291. QAction* pasteAction = contextMenu.addAction("粘贴");
  292. QAction* deleteAction = contextMenu.addAction("删除");
  293. QAction* onAction = contextMenu.addAction("置为ON");
  294. QAction* offAction = contextMenu.addAction("置为OFF");
  295. // 连接动作到现有功能
  296. connect(deleteAction, &QAction::triggered, this, &MainWindow::onActionDeleteTriggered);
  297. connect(copyAction, &QAction::triggered, this, &MainWindow::onActionCopyTriggered);
  298. connect(pasteAction, &QAction::triggered, this, &MainWindow::onActionPasteTriggered);
  299. contextMenu.exec(pos+QPoint(10, 10));
  300. }