Quellcode durchsuchen

界面的完善,PLC绘图的完善,hmi绘图的完善

main
email vor 2 Tagen
Ursprung
Commit
9369841db8
9 geänderte Dateien mit 935 neuen und 284 gelöschten Zeilen
  1. +18
    -0
      untitled/basedocument.h
  2. +21
    -5
      untitled/hmidocument.cpp
  3. +2
    -3
      untitled/hmidocument.h
  4. +54
    -1
      untitled/mainwindow.cpp
  5. +6
    -1
      untitled/mainwindow.h
  6. +767
    -232
      untitled/plcdocument.cpp
  7. +64
    -39
      untitled/plcdocument.h
  8. +2
    -2
      untitled/plcitems.cpp
  9. +1
    -1
      untitled/untitled.pro.user

+ 18
- 0
untitled/basedocument.h Datei anzeigen

@@ -23,10 +23,28 @@ public:
virtual bool saveToFile(const QString &filePath) = 0;
virtual bool loadFromFile(const QString &filePath) = 0;


// 设置变换矩阵
virtual void setTransform(const QTransform& transform) {
m_transform = transform;
update();
}

// 获取文档内容尺寸(子类需要重写)
virtual QSize getContentSize() const { return QSize(800, 600); } // 默认尺寸

// 重写paintEvent应用变换
// virtual void paintEvent(QPaintEvent *event) override {
// QPainter painter(this);
// painter.setTransform(m_transform);
// // 子类应调用父类的paintEvent? 或者自行绘制
// }

protected:
DocumentType m_type;
QString m_filePath;
bool m_modified = false;
QTransform m_transform;
};

#endif // BASEDOCUMENT_H

+ 21
- 5
untitled/hmidocument.cpp Datei anzeigen

@@ -29,22 +29,38 @@ HMIDocument::HMIDocument(QWidget *parent)
m_canDrawRectangle(false),
m_lastPastePos(0, 0)
{
// 创建绘图场景
// 创建绘图场景 - 固定大小
m_scene = new QGraphicsScene(this);
m_scene->setSceneRect(0, 0, 800, 600);
m_scene->setSceneRect(0, 0, 1000, 600); // 固定画布尺寸
m_scene->setBackgroundBrush(QBrush(Qt::lightGray));

// 创建视图
// 创建视图 - 关键修改:使用滚动区域包装
m_scrollArea = new QScrollArea(this);
m_scrollArea->setWidgetResizable(false); // 禁止内容自动调整大小
m_scrollArea->setFrameShape(QFrame::NoFrame); // 无边框

// 创建真正的视图部件
m_view = new QGraphicsView(m_scene, this);
m_view->setRenderHint(QPainter::Antialiasing);
m_view->setDragMode(QGraphicsView::RubberBandDrag);
m_view->setAcceptDrops(true);
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // 隐藏自身滚动条
m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

// 关键:视图固定大小与场景匹配
m_view->setMinimumSize(1000, 600);
m_view->setMaximumSize(1000, 600);
m_view->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
m_view->viewport()->installEventFilter(this);

// 布局(让视图占满文档区域)
// 添加视图到滚动区域
m_scrollArea->setWidget(m_view);
m_scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

// 设置主布局
auto layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(m_view);
layout->addWidget(m_scrollArea);
setLayout(layout);
}



+ 2
- 3
untitled/hmidocument.h Datei anzeigen

@@ -40,14 +40,12 @@ public:
bool loadFromFile(const QString &filePath) override;

void markModified();

signals:
void titleChanged(const QString &title);

protected:
bool eventFilter(QObject *obj, QEvent *event) override;

private:
private:
// 辅助方法
void createShape(const QString& type, const QPointF &pos);
void resetDrawFlags();
@@ -63,6 +61,7 @@ private:
QString m_title;
QGraphicsScene *m_scene;
QGraphicsView *m_view;
QScrollArea *m_scrollArea;
bool m_canDrawEllipse;
bool m_canDrawRectangle;



+ 54
- 1
untitled/mainwindow.cpp Datei anzeigen

@@ -17,7 +17,7 @@
#include <QFileDialog>
#include <QMessageBox>
#include <QTextEdit>
#include<QDockWidget>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
@@ -32,11 +32,64 @@ MainWindow::MainWindow(QWidget *parent)
connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, &MainWindow::onCloseTab);
createMenus();// 创建菜单和工具栏
createToolbars();
createLogPanel(); // 创建日志面板
}

MainWindow::~MainWindow()
{
}
void MainWindow::createLogPanel()
{
// 创建可停靠窗口
m_logDock = new QDockWidget("消息输出", this);
m_logDock->setAllowedAreas(Qt::BottomDockWidgetArea);
m_logDock->setFeatures(QDockWidget::DockWidgetClosable |
QDockWidget::DockWidgetMovable |
QDockWidget::DockWidgetFloatable); // 添加垂直标题栏

// 设置高度范围而非固定高度
m_logDock->setMinimumHeight(150);
m_logDock->setMaximumHeight(400);

// 创建主内容部件
QWidget* logWidget = new QWidget;
QVBoxLayout* logLayout = new QVBoxLayout;
logLayout->setContentsMargins(2, 2, 2, 2);

// 创建文本编辑框用于显示日志
m_logEdit = new QTextEdit;
m_logEdit->setReadOnly(true);
m_logEdit->setFont(QFont("Consolas", 10));
m_logEdit->setStyleSheet("background-color: #f8f8f8; border: 1px solid #d9d9d9;");
m_logEdit->setMinimumHeight(100);

// 创建控制按钮
QHBoxLayout* btnLayout = new QHBoxLayout;
m_clearLogBtn = new QPushButton("清空日志");

btnLayout->addWidget(m_clearLogBtn);
btnLayout->addStretch();

// 组合布局
logLayout->addLayout(btnLayout);
logLayout->addWidget(m_logEdit);
logWidget->setLayout(logLayout);

m_logDock->setWidget(logWidget);
addDockWidget(Qt::BottomDockWidgetArea, m_logDock);

// 初始显示状态
m_logDock->show();

// 连接信号
connect(m_clearLogBtn, &QPushButton::clicked, this, &MainWindow::onClearLogButtonClicked);
}
// 槽函数实现
void MainWindow::onClearLogButtonClicked()
{
m_logEdit->clear();
m_logEdit->append("日志已清空");
}

// 创建菜单栏
void MainWindow::createMenus()


+ 6
- 1
untitled/mainwindow.h Datei anzeigen

@@ -7,7 +7,7 @@
#include <QAction>
#include<QTextEdit>
#include "basedocument.h"
#include<QPushButton>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
@@ -31,9 +31,14 @@ private slots:
void onSaveAs(); // 另存为文档
void onOpen(); // 打开文档
void onCloseTab(int index); // 关闭标签页
void onClearLogButtonClicked();

private:
void createMenus(); // 创建菜单栏
QDockWidget* m_logDock;
QTextEdit* m_logEdit;
QPushButton* m_clearLogBtn;
void createLogPanel();
void createToolbars(); // 创建工具栏(左侧)
void updateToolBar(BaseDocument *doc); // 根据文档类型更新工具栏
void saveDocument(BaseDocument *doc); // 保存文档


+ 767
- 232
untitled/plcdocument.cpp
Datei-Diff unterdrückt, da er zu groß ist
Datei anzeigen


+ 64
- 39
untitled/plcdocument.h Datei anzeigen

@@ -1,13 +1,13 @@
// plcdocument.h
#ifndef PLCDOCUMENT_H
#define PLCDOCUMENT_H

#include "basedocument.h"
#include "plcitems.h" // 确保包含PLCItem的定义
#include "plcitems.h"
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsLineItem>
#include <QGraphicsRectItem>
#include <QGraphicsEllipseItem>
#include <QMap>
#include <QSet>
#include <QVector>
@@ -17,6 +17,10 @@
#include <QMimeData>
#include <QPair>

const int DEFAULT_ROWS = 11;
const int DEFAULT_COLUMNS = 15;
const int DEFAULT_CELL_SIZE = 70;

class PLCItem;
class ConnectionLine;

@@ -24,6 +28,19 @@ class PLCDocument : public BaseDocument
{
Q_OBJECT
public:
enum TerminalType {
NoTerminal = 0,
LeftTerminal,
RightTerminal,
RowTerminal
};

enum ConnectionSourceType {
ConnectionNone, // 无连接
ConnectionFromItem, // 起点是元件的端子
ConnectionFromRowTerminal // 起点是行触点
};

explicit PLCDocument(QWidget *parent = nullptr);
~PLCDocument() override;

@@ -34,28 +51,20 @@ public:
bool saveToFile(const QString &filePath) override;
bool loadFromFile(const QString &filePath) override;

// 创建PLC元件
void createPLCItem(const QString &type, const QPointF &pos);

// 连接管理
void startConnection(PLCItem *startItem);
void endConnection(PLCItem *endItem);
void startConnection(PLCItem *startItem, TerminalType startTerminal);
void startConnectionFromRowTerminal(int row);
void clearCurrentConnection();

// 运行状态控制
bool tryEndConnection(PLCItem *endItem, TerminalType endTerminal);
void setSimulationRunning(bool running);
void resetSimulation();
void setCurrentTool(const QString &tool) { m_currentTool = tool; }

// 获取表格参数
int rowCount() const { return m_rows; }
int columnCount() const { return m_columns; }
int cellSize() const { return m_cellSize; }

// 计算单元格中心位置
QPointF snapToCellCenter(const QPointF &pos) const;

// 检查并修正位置,确保在表格内
QPointF constrainToTable(const QPointF &pos) const;

void setTitle(const QString &title) { m_title = title; }
@@ -65,63 +74,79 @@ protected:
void resizeEvent(QResizeEvent *event) override;

private slots:
// 处理场景变化(用于更新连接线)
void handleSceneChanged();
void onRowTerminalConnection();

private:
// 表格管理
void createRealTable();
void clearTable();
void adjustTableToFitView(); // 调整表格以适应视图大小

// 项目位置改变处理
//void clearTable();
TerminalType whichTerminal(const QPointF& scenePos, PLCItem* item) const;
bool isTerminalUsed(PLCItem* item, TerminalType terminal) const;
void handleItemPositionChange(PLCItem *item);

// 仿真与连接管理
bool isCellOccupied(int col, int row, PLCItem* excludeItem) const;
void updateConnections();
void createContextMenu(QPoint globalPos);

// 根据类型创建PLC项 - 新增的辅助函数
PLCItem* createItemByType(PLCItem::ItemType type);
void removeInvalidConnectionsForItem(PLCItem* movedItem);
QList<PLCItem*> allPLCItems() const;

QGraphicsScene *m_scene;
QGraphicsView *m_view;
QString m_currentTool; // 当前选择的工具

// 连接管理
PLCItem *m_connectionStart = nullptr;
QString m_currentTool;
ConnectionSourceType m_connectionSourceType = ConnectionNone;
PLCItem *m_connectionStartItem = nullptr;
TerminalType m_startTerminal = NoTerminal;
int m_connectionStartRow = -1;
QGraphicsLineItem *m_tempLine = nullptr;
QList<ConnectionLine*> m_connections;

// 运行状态
QMap<PLCItem*, QMap<TerminalType, bool>> terminalConnections;
bool m_simulationRunning = false;
QSet<PLCItem*> m_activeItems;

// 表格参数 - 使用常量定义默认值
int m_rows = 15; // 表格行数
int m_columns = 20; // 表格列数
int m_cellSize = 50; // 单元格大小(像素)

// 表格图形项
int m_rows = DEFAULT_ROWS;
int m_columns = DEFAULT_COLUMNS;
int m_cellSize = DEFAULT_CELL_SIZE;
QGraphicsRectItem* m_tableFrame = nullptr;
QVector<QGraphicsLineItem*> m_horizontalLines;
QVector<QGraphicsLineItem*> m_verticalLines;
QString m_title; // 添加标题成员变量
QString m_title;
QVector<QGraphicsEllipseItem*> m_rowTerminals;
QMap<QGraphicsEllipseItem*, int> m_rowTerminalMap;
QMap<PLCItem*, QPointF> m_lastValidPositions;
QSet<PLCItem*> m_processingItems;
bool m_loadingFile = false;
};

// 连接线类
class ConnectionLine : public QGraphicsLineItem
{
public:
ConnectionLine(PLCItem *start, PLCItem *end, QGraphicsItem *parent = nullptr);
ConnectionLine(
PLCItem *startItem, PLCDocument::TerminalType startTerminal,
PLCItem *endItem, PLCDocument::TerminalType endTerminal,
QGraphicsItem *parent = nullptr
);

void updatePosition();

PLCItem* startItem() const { return m_startItem; }
PLCItem* endItem() const { return m_endItem; }
PLCDocument::TerminalType startTerminal() const { return m_startTerminal; }
PLCDocument::TerminalType endTerminal() const { return m_endTerminal; }
void setRowTerminalTargetRow(int row) { m_rowTerminalTargetRow = row; }
int rowTerminalTargetRow() const { return m_rowTerminalTargetRow; }
void setRowTerminalSourceRow(int row) { m_rowTerminalSourceRow = row; }
int rowTerminalSourceRow() const { return m_rowTerminalSourceRow; }
void setStartTerminalPoint(const QPointF& point) { m_startTerminalPoint = point; }
void setEndTerminalPoint(const QPointF& point) { m_endTerminalPoint = point; }

private:
PLCItem *m_startItem;
PLCDocument::TerminalType m_startTerminal;
PLCItem *m_endItem;
PLCDocument::TerminalType m_endTerminal;
QPointF m_startTerminalPoint;
QPointF m_endTerminalPoint;
int m_rowTerminalTargetRow = -1;
int m_rowTerminalSourceRow = -1;
};

#endif // PLCDOCUMENT_H

+ 2
- 2
untitled/plcitems.cpp Datei anzeigen

@@ -11,7 +11,7 @@ PLCItem::PLCItem(ItemType type, QGraphicsItem *parent)

QRectF PLCItem::boundingRect() const
{
return m_boundingRect; // 返回我们设置的边界矩形
return m_boundingRect; //返回我们设置的边界矩形
}

void PLCItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
@@ -104,7 +104,7 @@ void PLCItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
painter->drawLine(QPointF(-25, 0), QPointF(-15, 0)); // 左侧横线
painter->drawArc(QRectF(-15, -15, 15, 30), 90 * 16, 180 * 16);// 绘制左括号 "("
painter->drawArc(QRectF(0, -15, 15, 30), 270 * 16, 180 * 16);// 绘制右括号 ")"
painter->drawLine(QPointF(15, 0), QPointF(25, 0));// 右侧横线
//painter->drawLine(QPointF(15, 0), QPointF(25, 0));// 右侧横线
painter->setPen(QPen(Qt::black, 4));// 调整线条宽度使括号更清晰
break;
}


+ 1
- 1
untitled/untitled.pro.user Datei anzeigen

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.11.1, 2025-08-09T17:07:02. -->
<!-- Written by QtCreator 4.11.1, 2025-08-11T21:25:16. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>


Laden…
Abbrechen
Speichern