From 2aca5c5a839d5fa93226dfca2b1096d5a64e7a95 Mon Sep 17 00:00:00 2001 From: lipengpeng Date: Wed, 13 Aug 2025 10:16:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=A8PLC=E6=A8=A1=E5=9D=97=E7=9A=84?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=8C=BA=E6=B7=BB=E5=8A=A0=E4=BA=86=E7=BD=91?= =?UTF-8?q?=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- editor.pro | 2 ++ item.cpp | 50 ++++++++++++++++++++++++++++++++++++++++--- mainwindow.cpp | 58 ++++++++++++++++++++++++++++---------------------- mainwindow.h | 3 ++- myscene.cpp | 34 +++++++++++++++++++++++++++++ myscene.h | 30 ++++++++++++++++++++++++++ 6 files changed, 148 insertions(+), 29 deletions(-) create mode 100644 myscene.cpp create mode 100644 myscene.h diff --git a/editor.pro b/editor.pro index ab4e248..695bcfa 100644 --- a/editor.pro +++ b/editor.pro @@ -31,6 +31,7 @@ SOURCES += \ mainwindow.cpp \ modbusmanager.cpp \ mygraphicsview.cpp \ + myscene.cpp \ plc.cpp \ project.cpp \ registermanager.cpp @@ -48,6 +49,7 @@ HEADERS += \ mainwindow.h \ modbusmanager.h \ mygraphicsview.h \ + myscene.h \ plc.h \ project.h \ registermanager.h diff --git a/item.cpp b/item.cpp index 11d2a45..982fc0e 100644 --- a/item.cpp +++ b/item.cpp @@ -1,5 +1,6 @@ #include "item.h" #include "connection.h" +#include "myscene.h" #include #include #include @@ -120,9 +121,52 @@ void Item::handleMenuAction(QAction *action) QVariant Item::itemChange(GraphicsItemChange change, const QVariant &value) { - if (change == QGraphicsItem::ItemPositionChange) { - for (Connection* conn : connections_) - conn->updatePosition(); +// if (change == QGraphicsItem::ItemPositionChange) { +// for (Connection* conn : connections_) +// conn->updatePosition(); +// } +// if (change == ItemPositionChange && scene()) { +// // 获取场景(确保是 GridScene) +// if (auto myScene = dynamic_cast(scene())) { +// if (myScene->getSnapToGrid()) { +// // 获取网格大小 +// int gridSize = myScene->getGridSize(); + +// // 对齐到网格 +// QPointF newPos = value.toPointF(); +// qreal xV = qRound(newPos.x() / gridSize) * gridSize; +// qreal yV = qRound(newPos.y() / gridSize) * gridSize; +// return QPointF(xV, yV); +// } +// } +// } + // 处理位置即将改变事件(网格对齐) + if (change == ItemPositionChange && scene()) { + QPointF newPos = value.toPointF(); + + // 检查是否启用网格对齐 + if (auto myScene = dynamic_cast(scene())) { + if (myScene->getSnapToGrid()) { + int gridSize = myScene->getGridSize(); + + // 计算对齐位置 + qreal xV = qRound(newPos.x() / gridSize) * gridSize; + qreal yV = qRound(newPos.y() / gridSize) * gridSize; + + // 返回对齐后的位置 + return QPointF(xV, yV); + } + } + } + // 处理位置已改变事件(更新连线) + else if (change == QGraphicsItem::ItemPositionHasChanged) { + // 使用范围for循环安全遍历(防止在更新过程中连接被修改) + QList connectionsCopy = connections_; + for (Connection* conn : connectionsCopy) { + if (connections_.contains(conn)) { // 确保连接仍然存在 + conn->updatePosition(); + } + } } return QGraphicsObject::itemChange(change, value); } diff --git a/mainwindow.cpp b/mainwindow.cpp index e80ef4a..8b6aa4d 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -76,16 +76,20 @@ MainWindow::~MainWindow() void MainWindow::newPage(bool isPlc) { - // 创建新场景 - QGraphicsScene* newScene = new QGraphicsScene(this); - - // 创建新视图 - MyGraphicsView* newView = new MyGraphicsView(this); - newView->setScene(newScene); - newView->setSceneRect(0, 0, 800, 600); - newView->setDragMode(QGraphicsView::RubberBandDrag); - if (isPlc) { + // 创建新场景 + MyScene* newScene = new MyScene(this); + + // 设置网格属性 + newScene->setGridSize(20); // 20像素网格 + newScene->setGridColor(QColor(200, 200, 200, 150)); // 半透明灰色 + newScene->setSnapToGrid(true); // 启用对齐网格 + + // 创建新视图 + MyGraphicsView* newView = new MyGraphicsView(this); + newView->setScene(newScene); + newView->setSceneRect(0, 0, 800, 600); + newView->setDragMode(QGraphicsView::RubberBandDrag); // 添加到PLC标签页 int newIndex = ui->plc_tab_widget->addTab(newView, QString("页面 %1").arg(plcScenes.size() + 1)); plcPageTitles.append(""); // 初始化为空字符串 @@ -99,6 +103,14 @@ void MainWindow::newPage(bool isPlc) connect(newView, &MyGraphicsView::itemResetRegister, registerManager, &RegisterManager::unbindItem); } else { + // 创建新场景 + QGraphicsScene* newScene = new QGraphicsScene(this); + + // 创建新视图 + MyGraphicsView* newView = new MyGraphicsView(this); + newView->setScene(newScene); + newView->setSceneRect(0, 0, 800, 600); + newView->setDragMode(QGraphicsView::RubberBandDrag); // 添加到HMI标签页 int newIndex = ui->hmi_tab_widget->addTab(newView, QString("页面 %1").arg(hmiScenes.size() + 1)); hmiPageTitles.append(""); // 初始化为空字符串 @@ -425,18 +437,18 @@ void MainWindow::hmiChange() void MainWindow::newProject() { - // 检查当前tabwidget是否只有一个页面且页面内容为空 - if (currentIsPLC_ && plcScenes.size() == 1 && plcScenes[0]->items().isEmpty()) { - // 复用第一个页面 - clearScene(); - setWindowTitle("PLC编辑器"); - return; - } - if (!currentIsPLC_ && hmiScenes.size() == 1 && hmiScenes[0]->items().isEmpty()) { - clearScene(); - setWindowTitle("HMI编辑器"); - return; - } +// // 检查当前tabwidget是否只有一个页面且页面内容为空 +// if (currentIsPLC_ && plcScenes.size() == 1 && plcScenes[0]->items().isEmpty()) { +// // 复用第一个页面 +// clearScene(); +// setWindowTitle("PLC编辑器"); +// return; +// } +// if (!currentIsPLC_ && hmiScenes.size() == 1 && hmiScenes[0]->items().isEmpty()) { +// clearScene(); +// setWindowTitle("HMI编辑器"); +// return; +// } newPage(currentIsPLC_); // 更新窗口标题 @@ -569,10 +581,6 @@ void MainWindow::onListwidgetCurrenttextchanged(const QString ¤tText) void MainWindow::onTabCloseRequested(int index) { - if (plcScenes.size() == 1) { - QMessageBox::information(this, "提示", "至少保留一个页面"); - return; - } if (currentIsPLC_) { plcPageTitles.removeAt(index); diff --git a/mainwindow.h b/mainwindow.h index d7d0682..eaf5964 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -6,6 +6,7 @@ #include "hmi.h" #include "modbusmanager.h" #include "registermanager.h" +#include "myscene.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } @@ -47,7 +48,7 @@ private: RegisterManager* registerManager; ModbusManager* modbusManager; // PLC状态 - QList plcScenes; + QList plcScenes; QList plcViews; QStringList plcPageTitles; diff --git a/myscene.cpp b/myscene.cpp new file mode 100644 index 0000000..96c3e43 --- /dev/null +++ b/myscene.cpp @@ -0,0 +1,34 @@ +#include "myscene.h" +#include + +MyScene::MyScene(QObject *parent) : QGraphicsScene(parent) +{ + +} + +void MyScene::drawBackground(QPainter *painter, const QRectF &rect) +{ + QGraphicsScene::drawBackground(painter, rect); + + // 设置画笔 + QPen pen(gridColor); + pen.setWidth(1); + painter->setPen(pen); + + // 计算网格线 + qreal left = int(rect.left()) - (int(rect.left()) % gridSize); + qreal top = int(rect.top()) - (int(rect.top()) % gridSize); + + QVarLengthArray lines; + + for (qreal x = left; x < rect.right(); x += gridSize) { + lines.append(QLineF(x, rect.top(), x, rect.bottom())); + } + + for (qreal y = top; y < rect.bottom(); y += gridSize) { + lines.append(QLineF(rect.left(), y, rect.right(), y)); + } + + // 绘制网格 + painter->drawLines(lines.data(), lines.size()); +} diff --git a/myscene.h b/myscene.h new file mode 100644 index 0000000..c8fbb66 --- /dev/null +++ b/myscene.h @@ -0,0 +1,30 @@ +#ifndef MYSCENE_H +#define MYSCENE_H + +#include + +class MyScene : public QGraphicsScene +{ + Q_OBJECT + public: + explicit MyScene(QObject *parent = nullptr); + + // 网格属性设置 + void setGridSize(int size) { gridSize = size; } + int getGridSize() const { return gridSize; } + + void setGridColor(const QColor &color) { gridColor = color; } + QColor getGridColor() const { return gridColor; } + + void setSnapToGrid(bool snap) { snapToGrid = snap; } + bool getSnapToGrid() const { return snapToGrid; } + + void drawBackground(QPainter *painter, const QRectF &rect) override; + + private: + int gridSize = 20; // 网格大小(像素) + QColor gridColor = QColor(220, 220, 220); // 网格颜色(浅灰色) + bool snapToGrid = true; // 是否启用对齐网格 +}; + +#endif // MYSCENE_H