|
|
@@ -1,23 +1,47 @@ |
|
|
|
#include "mainwindow.h" |
|
|
|
#include "ui_mainwindow.h" |
|
|
|
#include"hmiwidget.h" |
|
|
|
|
|
|
|
#include<QDebug> |
|
|
|
#include<QDir> |
|
|
|
#include <QGraphicsView> |
|
|
|
#include <QGraphicsScene> |
|
|
|
MainWindow::MainWindow(QWidget *parent) |
|
|
|
: QMainWindow(parent) |
|
|
|
, ui(new Ui::MainWindow) |
|
|
|
,canDrawCircle(false) |
|
|
|
,canDrawEllipse(false) |
|
|
|
,canDrawRectangle(false) |
|
|
|
{ |
|
|
|
ui->setupUi(this); |
|
|
|
addDockWidget(Qt::BottomDockWidgetArea, ui->dockWidget_3);//将dockWidget_3添加到主窗口的下方 |
|
|
|
|
|
|
|
scene = new QGraphicsScene(this); |
|
|
|
scene->setSceneRect(0, 0, 800, 600);//因为场景初始无内容时,QGraphicsView 自动将场景中心与视图中心对齐 |
|
|
|
scene->setBackgroundBrush(QBrush(Qt::lightGray)); |
|
|
|
|
|
|
|
ui->graphicsView_2->setScene(scene); |
|
|
|
ui->graphicsView_2->setRenderHint(QPainter::Antialiasing); |
|
|
|
ui->graphicsView_2->setDragMode(QGraphicsView::RubberBandDrag); |
|
|
|
ui->graphicsView_2->setAcceptDrops(true);// 启用视图的拖放功能(接收拖拽) |
|
|
|
ui->graphicsView_2->viewport()->installEventFilter(this); |
|
|
|
ui->treeWidget_2->setDragEnabled(true);// 允许拖拽 |
|
|
|
ui->treeWidget_2->setDragDropMode(QAbstractItemView::DragOnly);// 仅拖拽 |
|
|
|
|
|
|
|
ui->actiondelete->setShortcut(QKeySequence::Delete);//设置快捷键 |
|
|
|
ui->actioncopy->setShortcut(QKeySequence::Copy); |
|
|
|
ui->actionpaste->setShortcut(QKeySequence::Paste); |
|
|
|
|
|
|
|
ui->treeWidget->topLevelItem(0)->setIcon(0, QIcon("../two/IntegratedPlatform/images/T-常开触点-01.png")); |
|
|
|
ui->treeWidget->topLevelItem(1)->setIcon(0, QIcon("../two/IntegratedPlatform/images/T-常闭触点-01-01.png")); |
|
|
|
ui->treeWidget->topLevelItem(2)->setIcon(0, QIcon("../two/IntegratedPlatform/images/大于等于.png")); |
|
|
|
ui->treeWidget->topLevelItem(3)->setIcon(0, QIcon("../two/IntegratedPlatform/images/线-圈-圈.png")); |
|
|
|
ui->treeWidget_2->topLevelItem(0)->setIcon(0, QIcon("../two/IntegratedPlatform/images/灯泡.png")); |
|
|
|
ui->treeWidget_2->topLevelItem(1)->setIcon(0, QIcon("../two/IntegratedPlatform/images/按钮.png")); |
|
|
|
|
|
|
|
connect(ui->treeWidget_2, &QTreeWidget::itemClicked, this, &MainWindow::onHmiItemClicked); |
|
|
|
ui-> graphicsView_2->viewport()->installEventFilter(this); |
|
|
|
connect(ui->actiondelete, &QAction::triggered, this, &MainWindow::onActionDeleteTriggered); |
|
|
|
connect(ui->actioncopy, &QAction::triggered, this, &MainWindow::onActionCopyTriggered); |
|
|
|
connect(ui->actionpaste, &QAction::triggered, this, &MainWindow::onActionPasteTriggered); |
|
|
|
|
|
|
|
addDockWidget(Qt::BottomDockWidgetArea, ui->dockWidget_3);//将dockWidget_3添加到主窗口的下方 |
|
|
|
ui->treeWidget_2->topLevelItem(0)->setIcon(0, QIcon("C:/Users/admin/Desktop/灯泡.png")); |
|
|
|
ui->treeWidget_2->topLevelItem(1)->setIcon(0, QIcon("C:/Users/admin/Desktop/按钮.png")); |
|
|
|
} |
|
|
|
|
|
|
|
MainWindow::~MainWindow() |
|
|
@@ -29,58 +53,261 @@ void MainWindow::onHmiItemClicked(QTreeWidgetItem *item) |
|
|
|
{ |
|
|
|
if (item->text(0) == "指示灯") |
|
|
|
{ |
|
|
|
canDrawCircle = true; |
|
|
|
canDrawEllipse = true; |
|
|
|
canDrawRectangle = false; |
|
|
|
} |
|
|
|
else if(item->text(0) == "按钮") |
|
|
|
else if (item->text(0) == "按钮") |
|
|
|
{ |
|
|
|
canDrawCircle=false; |
|
|
|
canDrawRectangle = true;//如果点击的是按钮,则不允许绘制灯 |
|
|
|
canDrawEllipse = false; |
|
|
|
canDrawRectangle = true; |
|
|
|
} |
|
|
|
else { |
|
|
|
canDrawRectangle = false;//如果点击的是灯,则不允许绘制按钮 |
|
|
|
canDrawCircle = false; |
|
|
|
else |
|
|
|
{ |
|
|
|
canDrawEllipse = false; |
|
|
|
canDrawRectangle = false; |
|
|
|
} |
|
|
|
} |
|
|
|
bool MainWindow::eventFilter(QObject *obj, QEvent *event) |
|
|
|
{ |
|
|
|
// 修正1:使用一致的视图对象名(graphicsView_2) |
|
|
|
if (obj != ui->graphicsView_2->viewport()) { |
|
|
|
return false; // 不是我们关心的对象,不处理 |
|
|
|
if (obj != ui->graphicsView_2->viewport()) |
|
|
|
{ |
|
|
|
return QMainWindow::eventFilter(obj, event); |
|
|
|
} |
|
|
|
// 只处理鼠标按下事件 |
|
|
|
if (event->type() == QEvent::MouseButtonPress) { |
|
|
|
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); |
|
|
|
if (mouseEvent->button() == Qt::LeftButton) { |
|
|
|
// 获取点击的场景坐标 |
|
|
|
if (event->type() == QEvent::MouseButtonPress)//点击生成 |
|
|
|
{ |
|
|
|
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); |
|
|
|
if (mouseEvent->button() == Qt::RightButton)//打开右键菜单 |
|
|
|
{ |
|
|
|
QPointF scenePos = ui->graphicsView_2->mapToScene(mouseEvent->pos()); |
|
|
|
|
|
|
|
// 根据标志绘制元素 |
|
|
|
if (canDrawCircle) { |
|
|
|
ResizableEllipse *circle = new ResizableEllipse( |
|
|
|
scenePos.x(), scenePos.y(), 50, 50); |
|
|
|
circle->setBrush(QBrush(Qt::red)); // 设置指示灯颜色 |
|
|
|
scene->addItem(circle); |
|
|
|
QGraphicsItem *item = scene->itemAt(scenePos, ui->graphicsView_2->transform()); |
|
|
|
if (item && !item->isSelected())// 如果有项在点击位置,选中它并清除其他选择 |
|
|
|
{ |
|
|
|
scene->clearSelection(); // 清除所有当前选择 |
|
|
|
item->setSelected(true); // 选中当前项 |
|
|
|
} |
|
|
|
else if (canDrawRectangle) { |
|
|
|
ResizableRectangle *rectangle = new ResizableRectangle( |
|
|
|
scenePos.x(), scenePos.y(), 100, 50); |
|
|
|
rectangle->setBrush(QBrush(Qt::yellow)); // 设置按钮颜色 |
|
|
|
scene->addItem(rectangle); |
|
|
|
QPoint globalPos = mouseEvent->globalPos(); |
|
|
|
showContextMenu(globalPos); |
|
|
|
return true; |
|
|
|
} |
|
|
|
if (mouseEvent->button() == Qt::LeftButton) |
|
|
|
{ |
|
|
|
QPointF scenePos = ui->graphicsView_2->mapToScene(mouseEvent->pos()); |
|
|
|
QGraphicsItem *item = scene->itemAt(scenePos, ui->graphicsView_2->transform()); |
|
|
|
if (item) |
|
|
|
{ |
|
|
|
return QMainWindow::eventFilter(obj, event); |
|
|
|
} |
|
|
|
|
|
|
|
// 重置绘制标志 |
|
|
|
canDrawCircle = false; |
|
|
|
canDrawRectangle = false; |
|
|
|
|
|
|
|
// 修正2:使用一致的树控件对象名(treeWidget_2) |
|
|
|
if (ui->treeWidget_2->currentItem()) { |
|
|
|
ui->treeWidget_2->currentItem()->setSelected(false); |
|
|
|
if (canDrawEllipse) |
|
|
|
{ |
|
|
|
createEllipse(scenePos); // 封装为函数,避免重复代码 |
|
|
|
resetDrawFlags(); |
|
|
|
} |
|
|
|
|
|
|
|
return true; // 事件已处理 |
|
|
|
else if (canDrawRectangle) |
|
|
|
{ |
|
|
|
createRectangle(scenePos); // 封装为函数 |
|
|
|
resetDrawFlags(); |
|
|
|
} |
|
|
|
if (!item) |
|
|
|
{ |
|
|
|
scene->clearSelection(); |
|
|
|
if (ui->treeWidget_2->currentItem()) |
|
|
|
{ |
|
|
|
ui->treeWidget_2->currentItem()->setSelected(false); |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
//拖拽生成 |
|
|
|
if (event->type() == QEvent::DragEnter) |
|
|
|
{ |
|
|
|
QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent*>(event); |
|
|
|
if (dragEvent->source() == ui->treeWidget_2)//检查拖拽源是否为树控件,并接受拖拽 |
|
|
|
{ |
|
|
|
dragEvent->acceptProposedAction(); |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
// 拖拽移动(可选:显示拖拽反馈) |
|
|
|
if (event->type() == QEvent::DragMove) |
|
|
|
{ |
|
|
|
QDragMoveEvent *dragEvent = static_cast<QDragMoveEvent*>(event); |
|
|
|
dragEvent->acceptProposedAction(); |
|
|
|
return true; |
|
|
|
} |
|
|
|
// 拖拽释放(生成图形) |
|
|
|
if (event->type() == QEvent::Drop) |
|
|
|
{ |
|
|
|
QDropEvent *dropEvent = static_cast<QDropEvent*>(event); |
|
|
|
QModelIndex index = ui->treeWidget_2->currentIndex();// 获取拖拽的树项 |
|
|
|
if (!index.isValid()) return true; |
|
|
|
QTreeWidgetItem *item = ui->treeWidget_2->currentItem(); |
|
|
|
if (!item) return true; |
|
|
|
QPointF scenePos = ui->graphicsView_2->mapToScene(dropEvent->pos());// 计算释放位置(转换为场景坐标) |
|
|
|
if (item->text(0) == "指示灯") |
|
|
|
{ |
|
|
|
createEllipse(scenePos); |
|
|
|
} |
|
|
|
else if (item->text(0) == "按钮") |
|
|
|
{ |
|
|
|
createRectangle(scenePos); |
|
|
|
} |
|
|
|
dropEvent->acceptProposedAction(); |
|
|
|
return true; |
|
|
|
} |
|
|
|
// 修正3:正确处理未过滤的事件 |
|
|
|
return QMainWindow::eventFilter(obj, event); |
|
|
|
} |
|
|
|
//删除 |
|
|
|
void MainWindow::onActionDeleteTriggered() |
|
|
|
{ |
|
|
|
QList<QGraphicsItem*> selectedItems = scene->selectedItems();//获取场景中所有选中的项 |
|
|
|
foreach (QGraphicsItem *item, selectedItems)//遍历并删除所有选中的项 |
|
|
|
{ |
|
|
|
scene->removeItem(item); |
|
|
|
delete item;//删除对象 |
|
|
|
} |
|
|
|
} |
|
|
|
// 复制功能 |
|
|
|
void MainWindow::onActionCopyTriggered() |
|
|
|
{ |
|
|
|
copiedItemsData.clear(); |
|
|
|
QList<QGraphicsItem*> selectedItems = scene->selectedItems(); |
|
|
|
if (selectedItems.isEmpty()) return; |
|
|
|
foreach (QGraphicsItem *item, selectedItems) |
|
|
|
{ |
|
|
|
QByteArray itemData; |
|
|
|
QDataStream stream(&itemData, QIODevice::WriteOnly); |
|
|
|
stream << item->type();// 基础属性 |
|
|
|
stream << item->pos(); |
|
|
|
stream << item->flags(); |
|
|
|
stream << item->transform(); |
|
|
|
stream << item->isVisible(); |
|
|
|
if (auto shapeItem = dynamic_cast<QAbstractGraphicsShapeItem*>(item))//处理所有图形形状项 |
|
|
|
{ |
|
|
|
stream << shapeItem->pen(); |
|
|
|
stream << shapeItem->brush(); |
|
|
|
stream << shapeItem->boundingRect(); |
|
|
|
} |
|
|
|
if (auto resizableRect = dynamic_cast<ResizableRectangle*>(item))//处理矩形圆形两项,存储几何信息 |
|
|
|
{ |
|
|
|
stream << resizableRect->rect();//实际存储的矩形 |
|
|
|
} |
|
|
|
else if (auto resizableEllipse = dynamic_cast<ResizableEllipse*>(item)) |
|
|
|
{ |
|
|
|
stream << resizableEllipse->rect(); |
|
|
|
} |
|
|
|
copiedItemsData.append(itemData); |
|
|
|
} |
|
|
|
lastPastePos = selectedItems.first()->pos(); |
|
|
|
} |
|
|
|
|
|
|
|
// 粘贴功能 |
|
|
|
void MainWindow::onActionPasteTriggered() |
|
|
|
{ |
|
|
|
if (copiedItemsData.isEmpty()) return; |
|
|
|
QPointF offset(20,20); |
|
|
|
lastPastePos+=offset; |
|
|
|
scene->clearSelection(); |
|
|
|
foreach (const QByteArray &itemData, copiedItemsData) |
|
|
|
{ |
|
|
|
QDataStream stream(itemData); |
|
|
|
int itemType; |
|
|
|
QPointF pos; |
|
|
|
QGraphicsItem::GraphicsItemFlags flags; |
|
|
|
QTransform transform; |
|
|
|
bool visible; |
|
|
|
stream >> itemType >> pos >> flags >> transform >> visible; |
|
|
|
QGraphicsItem *newItem = nullptr; |
|
|
|
switch (itemType) |
|
|
|
{ |
|
|
|
case QGraphicsRectItem::Type: |
|
|
|
{ |
|
|
|
QPen pen; |
|
|
|
QBrush brush; |
|
|
|
QRectF rect; |
|
|
|
stream >> pen >> brush >> rect; |
|
|
|
ResizableRectangle *rectItem = new ResizableRectangle(rect.x(), rect.y(), rect.width(), rect.height()); |
|
|
|
rectItem->setPen(pen); |
|
|
|
rectItem->setBrush(brush); |
|
|
|
newItem = rectItem; |
|
|
|
break; |
|
|
|
} |
|
|
|
case QGraphicsEllipseItem::Type: |
|
|
|
{ |
|
|
|
QPen pen; |
|
|
|
QBrush brush; |
|
|
|
QRectF rect; |
|
|
|
stream >> pen >> brush >> rect; |
|
|
|
ResizableEllipse *ellipseItem = new ResizableEllipse(rect.x(), rect.y(), rect.width(), rect.height()); |
|
|
|
ellipseItem->setPen(pen); |
|
|
|
ellipseItem->setBrush(brush); |
|
|
|
newItem = ellipseItem; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (newItem) { |
|
|
|
scene->addItem(newItem); |
|
|
|
newItem->setPos(lastPastePos); |
|
|
|
newItem->setFlags(flags); |
|
|
|
newItem->setTransform(transform); |
|
|
|
newItem->setVisible(visible); |
|
|
|
newItem->setSelected(true); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::createEllipse(const QPointF &pos) |
|
|
|
{ |
|
|
|
ResizableEllipse *ellipse = new ResizableEllipse(pos.x(), pos.y(), 50, 50); |
|
|
|
ellipse->setBrush(QBrush(Qt::red)); |
|
|
|
ellipse->setPen(QPen(Qt::black, 1)); |
|
|
|
scene->addItem(ellipse); |
|
|
|
ellipse->setSelected(true); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::createRectangle(const QPointF &pos) |
|
|
|
{ |
|
|
|
ResizableRectangle *rectangle = new ResizableRectangle(pos.x(), pos.y(), 100, 50); |
|
|
|
rectangle->setBrush(QBrush(Qt::yellow)); |
|
|
|
rectangle->setPen(QPen(Qt::black, 1)); |
|
|
|
scene->addItem(rectangle); |
|
|
|
rectangle->setSelected(true); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::resetDrawFlags() |
|
|
|
{ |
|
|
|
canDrawEllipse = false; |
|
|
|
canDrawRectangle = false; |
|
|
|
if (ui->treeWidget_2->currentItem()) |
|
|
|
{ |
|
|
|
ui->treeWidget_2->currentItem()->setSelected(false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::showContextMenu(QPoint pos) |
|
|
|
{ |
|
|
|
QPoint viewportPos = ui->graphicsView_2->mapFromGlobal(pos); |
|
|
|
QPointF scenePos = ui->graphicsView_2->mapToScene(viewportPos); |
|
|
|
QGraphicsItem* clickedItem = scene->itemAt(scenePos, ui->graphicsView_2->transform());//检查是否有图形项在点击位置 |
|
|
|
QMenu contextMenu(this); |
|
|
|
if (!clickedItem) |
|
|
|
{ |
|
|
|
QAction* pasteAction = contextMenu.addAction("粘贴");// 空白处右键:只添加粘贴选项 |
|
|
|
pasteAction->setEnabled(!copiedItemsData.isEmpty()); |
|
|
|
connect(pasteAction, &QAction::triggered, this, &MainWindow::onActionPasteTriggered); |
|
|
|
contextMenu.exec(pos+QPoint(10, 10)); |
|
|
|
return; |
|
|
|
} |
|
|
|
// 添加动作 |
|
|
|
QAction* propertiesAction = contextMenu.addAction("属性"); |
|
|
|
QAction* copyAction = contextMenu.addAction("复制"); |
|
|
|
QAction* pasteAction = contextMenu.addAction("粘贴"); |
|
|
|
QAction* deleteAction = contextMenu.addAction("删除"); |
|
|
|
QAction* onAction = contextMenu.addAction("置为ON"); |
|
|
|
QAction* offAction = contextMenu.addAction("置为OFF"); |
|
|
|
// 连接动作到现有功能 |
|
|
|
connect(deleteAction, &QAction::triggered, this, &MainWindow::onActionDeleteTriggered); |
|
|
|
connect(copyAction, &QAction::triggered, this, &MainWindow::onActionCopyTriggered); |
|
|
|
connect(pasteAction, &QAction::triggered, this, &MainWindow::onActionPasteTriggered); |
|
|
|
contextMenu.exec(pos+QPoint(10, 10)); |
|
|
|
} |