@@ -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 | |||
@@ -1,5 +1,6 @@ | |||
#include "item.h" | |||
#include "connection.h" | |||
#include "myscene.h" | |||
#include <QMenu> | |||
#include <QPainter> | |||
#include <QStyleOptionGraphicsItem> | |||
@@ -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<MyScene*>(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<MyScene*>(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<Connection*> connectionsCopy = connections_; | |||
for (Connection* conn : connectionsCopy) { | |||
if (connections_.contains(conn)) { // 确保连接仍然存在 | |||
conn->updatePosition(); | |||
} | |||
} | |||
} | |||
return QGraphicsObject::itemChange(change, value); | |||
} | |||
@@ -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); | |||
@@ -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<QGraphicsScene*> plcScenes; | |||
QList<MyScene*> plcScenes; | |||
QList<MyGraphicsView*> plcViews; | |||
QStringList plcPageTitles; | |||
@@ -0,0 +1,34 @@ | |||
#include "myscene.h" | |||
#include <QPainter> | |||
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<QLineF, 100> 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()); | |||
} |
@@ -0,0 +1,30 @@ | |||
#ifndef MYSCENE_H | |||
#define MYSCENE_H | |||
#include <QGraphicsScene> | |||
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 |