Bläddra i källkod

HMI模块的多页面编辑

master
鹏鹏 李 2 dagar sedan
förälder
incheckning
a232f5c546
9 ändrade filer med 132 tillägg och 87 borttagningar
  1. +63
    -16
      hmi.cpp
  2. +7
    -3
      hmi.h
  3. +3
    -33
      hmi.ui
  4. +33
    -10
      mainwindow.cpp
  5. +1
    -0
      mainwindow.h
  6. +11
    -1
      mainwindow.ui
  7. +11
    -11
      plc.cpp
  8. +1
    -1
      plc.h
  9. +2
    -12
      plc.ui

+ 63
- 16
hmi.cpp Visa fil

@@ -8,6 +8,7 @@
#include <QDropEvent>
#include <QGraphicsView>
#include <QMessageBox>
#include <QVBoxLayout>
#include "creatitem.h"

HMI::HMI(QWidget *parent) :
@@ -15,11 +16,9 @@ HMI::HMI(QWidget *parent) :
ui(new Ui::HMI)
{
ui->setupUi(this);
/* 1. 场景 */
hmi_scene_ = new QGraphicsScene(this);
ui->graphicsView->setScene(hmi_scene_);
ui->graphicsView->setSceneRect(0, 0, 800, 600);
ui->graphicsView->setDragMode(QGraphicsView::RubberBandDrag);

ui->tabWidget->setTabsClosable(true);
ui->tabWidget->setMovable(true);

/* 2. 列表 */
ui->listWidget->setViewMode(QListView::IconMode);
@@ -27,16 +26,53 @@ HMI::HMI(QWidget *parent) :
ui->listWidget->setDragEnabled(false);
ui->listWidget->viewport()->installEventFilter(this);

// 创建初始页面
newPage();
/* 3. 填充列表 */
createComponents();
connect(ui->listWidget,&QListWidget::currentTextChanged,this,&HMI::onListwidgetCurrenttextchanged);

// 连接标签页信号
// connect(ui->tabWidget, &QTabWidget::currentChanged, this, &HMI::onTabChanged);
connect(ui->tabWidget, &QTabWidget::tabCloseRequested, [this](int index) {
if (scenes.size() > 1) {
delete scenes.takeAt(index);
delete views.takeAt(index);
ui->tabWidget->removeTab(index);
} else {
QMessageBox::information(this, "提示", "至少保留一个页面");
}
});
}

HMI::~HMI()
{
qDeleteAll(scenes);
qDeleteAll(views);
delete ui;
}

void HMI::newPage()
{
// 创建新场景
QGraphicsScene* newScene = new QGraphicsScene(this);
// 创建新视图
MyGraphicsView* newView = new MyGraphicsView(ui->tabWidget);
newView->setScene(newScene);
newView->setSceneRect(0, 0, 800, 600);
newView->setDragMode(QGraphicsView::RubberBandDrag);
// 添加到标签页
int newIndex = ui->tabWidget->addTab(newView, QString("页面 %1").arg(scenes.size() + 1));
ui->tabWidget->setCurrentIndex(newIndex);
// 保存场景和视图
scenes.append(newScene);
views.append(newView);
}

bool HMI::eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->listWidget->viewport()) {
@@ -102,32 +138,43 @@ void HMI::createComponents()

void HMI::clearScene()
{
hmi_scene_->clear();
if (currentPageIndex() >= 0 && currentPageIndex() < scenes.size()) {
scenes[currentPageIndex()]->clear();
}
}

void HMI::applyProjectToScene(const Project& proj)
int HMI::currentPageIndex() const
{
clearScene();
return ui->tabWidget->currentIndex();
}

void HMI::applyProjectToScene(const Project& proj, int pageIndex)
{
if (pageIndex < 0 || pageIndex >= scenes.size())
return;

scenes[pageIndex]->clear();
QVector<Item*> itemObjs;
for (const auto& d : proj.items_) {
Item* item = creatItem(d.type);
if (!item) continue;
item->setPos(d.x, d.y);
item->setRegisterId(d.registerId);
connect(item, &Item::requestCopy, ui->graphicsView, &MyGraphicsView::onItemRequestCopy);
connect(item, &Item::requestDelete, ui->graphicsView, &MyGraphicsView::onItemRequestDelete);
connect(item, &Item::requestBindRegister, ui->graphicsView, &MyGraphicsView::onItemRequestBindRegister);
hmi_scene_->addItem(item);
connect(item, &Item::requestCopy, views[pageIndex], &MyGraphicsView::onItemRequestCopy);
connect(item, &Item::requestDelete, views[pageIndex], &MyGraphicsView::onItemRequestDelete);
connect(item, &Item::requestBindRegister, views[pageIndex], &MyGraphicsView::onItemRequestBindRegister);
scenes[pageIndex]->addItem(item);
itemObjs.append(item);
}
}

void HMI::extractSceneToProject(Project& proj)
void HMI::extractSceneToProject(Project& proj, int pageIndex)
{
if (pageIndex < 0 || pageIndex >= scenes.size()) return;
proj.clear();
QList<Item*> items;
for (QGraphicsItem* gi : hmi_scene_->items()) {
if (Item* it = dynamic_cast<Item*>(gi)) {
for (QGraphicsItem* gi : scenes[pageIndex]->items()){
if (Item* it = dynamic_cast<Item*>(gi)){
items.append(it);
}
}
@@ -139,7 +186,7 @@ void HMI::extractSceneToProject(Project& proj)
d.registerId = it->registerId();
proj.items_.append(d);
}
for (QGraphicsItem* gi : hmi_scene_->items()) {
for (QGraphicsItem* gi : scenes[pageIndex]->items()) {
if (Connection* conn = dynamic_cast<Connection*>(gi)) {
int fromIdx = items.indexOf(conn->from_);
int toIdx = items.indexOf(conn->to_);


+ 7
- 3
hmi.h Visa fil

@@ -4,6 +4,7 @@
#include <QGraphicsScene>
#include <QWidget>
#include <project.h>
#include "mygraphicsview.h"

namespace Ui {
class HMI;
@@ -16,11 +17,13 @@ class HMI : public QWidget
public:
explicit HMI(QWidget *parent = nullptr);
~HMI();
void newPage();
void createComponents();

void clearScene();
void applyProjectToScene(const Project& proj);
void extractSceneToProject(Project& proj);
void applyProjectToScene(const Project& proj, int pageIndex = 0); // 添加页面索引参数
void extractSceneToProject(Project& proj, int pageIndex = 0); // 添加页面索引参数
int currentPageIndex() const; // 获取当前页面索引

protected:
bool eventFilter(QObject *obj, QEvent *event) override;
@@ -30,7 +33,8 @@ private slots:

private:
Ui::HMI *ui;
QGraphicsScene *hmi_scene_;
QList<QGraphicsScene*> scenes; // 存储多个场景
QList<MyGraphicsView*> views; // 存储多个视图
QString selectedComponentType;
};



+ 3
- 33
hmi.ui Visa fil

@@ -19,7 +19,7 @@
<x>10</x>
<y>30</y>
<width>171</width>
<height>451</height>
<height>431</height>
</rect>
</property>
</widget>
@@ -29,44 +29,14 @@
<x>190</x>
<y>10</y>
<width>781</width>
<height>481</height>
<height>451</height>
</rect>
</property>
<property name="currentIndex">
<number>0</number>
<number>-1</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Tab 1</string>
</attribute>
<widget class="MyGraphicsView" name="graphicsView">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>761</width>
<height>451</height>
</rect>
</property>
<property name="dragMode">
<enum>QGraphicsView::NoDrag</enum>
</property>
</widget>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Tab 2</string>
</attribute>
</widget>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>MyGraphicsView</class>
<extends>QGraphicsView</extends>
<header>mygraphicsview.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

+ 33
- 10
mainwindow.cpp Visa fil

@@ -35,7 +35,7 @@ MainWindow::MainWindow(QWidget *parent)
connect(ui->action_disconnect, &QAction::triggered, this, &MainWindow::disconnection);

connect(modbusManager, &ModbusManager::connectionStatusChanged,
plc_, &PLC::updateConnectionStatus);
this, &MainWindow::updateConnectionStatus);


plc_->applyProjectToScene(plcProject_); // 初始空
@@ -71,9 +71,11 @@ void MainWindow::newProject()
plc_->clearScene();
setWindowTitle("未命名项目 - PLC编辑器");
} else {
hmiProject_.clear();
hmi_->newPage();
hmiProject_.clear(); // 清除项目数据
hmiFilePath_.clear();
hmi_->clearScene();

// 更新窗口标题
setWindowTitle("未命名项目 - HMI编辑器");
}
}
@@ -99,14 +101,20 @@ void MainWindow::openProject()
{
QString filePath = QFileDialog::getOpenFileName(this, "打开项目", "", "项目文件 (*.hmiproj)");
if (filePath.isEmpty()) return;
if (hmiProject_.loadFromFile(filePath))
{

Project newProject;
if (newProject.loadFromFile(filePath)) {
// 创建新页面
hmi_->newPage();

// 应用项目到新页面
int newPageIndex = hmi_->currentPageIndex();
hmi_->applyProjectToScene(newProject, newPageIndex);

// 保存文件路径
hmiFilePath_ = filePath;
hmi_->applyProjectToScene(hmiProject_);
setWindowTitle(QFileInfo(hmiFilePath_).fileName() + " - HMI编辑器");
}
else
{
} else {
QMessageBox::critical(this, "错误", "无法打开HMI项目文件");
}
}
@@ -134,7 +142,10 @@ void MainWindow::saveProject()
filePath += ".hmiproj";
hmiFilePath_ = filePath;
}
hmi_->extractSceneToProject(hmiProject_);

// 从当前页面提取项目
hmi_->extractSceneToProject(hmiProject_, hmi_->currentPageIndex());

if (!hmiProject_.saveToFile(hmiFilePath_)) {
QMessageBox::critical(this, "错误", "保存项目失败");
}
@@ -152,3 +163,15 @@ void MainWindow::disconnection()
modbusManager->disconnectDevice();
modbusManager->stopSimulation();
}

void MainWindow::updateConnectionStatus(bool connection)
{
if (connection)
{
ui->textEdit->append("连接");
}
else
{
ui->textEdit->append("断开");
}
}

+ 1
- 0
mainwindow.h Visa fil

@@ -28,6 +28,7 @@ private slots:
void saveProject();
void connection();
void disconnection();
void updateConnectionStatus(bool connection);

private:
Ui::MainWindow *ui;


+ 11
- 1
mainwindow.ui Visa fil

@@ -20,7 +20,17 @@
<x>10</x>
<y>0</y>
<width>981</width>
<height>561</height>
<height>511</height>
</rect>
</property>
</widget>
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>20</x>
<y>470</y>
<width>951</width>
<height>141</height>
</rect>
</property>
</widget>


+ 11
- 11
plc.cpp Visa fil

@@ -237,14 +237,14 @@ void PLC::btnInsertClicked()
ui->graphicsView->scene()->addItem(c2);
}

void PLC::updateConnectionStatus(bool connection)
{
if (connection)
{
ui->textEdit->append("连接");
}
else
{
ui->textEdit->append("断开");
}
}
//void PLC::updateConnectionStatus(bool connection)
//{
// if (connection)
// {
// ui->textEdit->append("连接");
// }
// else
// {
// ui->textEdit->append("断开");
// }
//}

+ 1
- 1
plc.h Visa fil

@@ -30,7 +30,7 @@ public slots:
void onListwidgetCurrenttextchanged(const QString &currentText);
void btnInsertClicked();

void updateConnectionStatus(bool connection);
// void updateConnectionStatus(bool connection);

private:
Ui::PLC *ui;


+ 2
- 12
plc.ui Visa fil

@@ -19,7 +19,7 @@
<x>10</x>
<y>30</y>
<width>171</width>
<height>401</height>
<height>431</height>
</rect>
</property>
</widget>
@@ -29,7 +29,7 @@
<x>200</x>
<y>30</y>
<width>761</width>
<height>401</height>
<height>431</height>
</rect>
</property>
<property name="dragMode">
@@ -49,16 +49,6 @@
<string>插入</string>
</property>
</widget>
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>10</x>
<y>440</y>
<width>951</width>
<height>87</height>
</rect>
</property>
</widget>
</widget>
<customwidgets>
<customwidget>


Laddar…
Avbryt
Spara