Browse Source

完善实现细节,实现文件新增功能

master
付春阳 2 days ago
parent
commit
8aca58a684
6 changed files with 207 additions and 6 deletions
  1. +38
    -1
      customgraphics.cpp
  2. +7
    -0
      customgraphics.h
  3. +108
    -2
      hmimodule.cpp
  4. +11
    -0
      hmimodule.h
  5. +41
    -2
      mainwindow.cpp
  6. +2
    -1
      mainwindow.h

+ 38
- 1
customgraphics.cpp View File

@@ -86,6 +86,26 @@ void HmiComponent::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
QMenu menu; QMenu menu;


QAction *propertyAction = menu.addAction("属性"); QAction *propertyAction = menu.addAction("属性");

QAction *setOnAction = nullptr;
QAction *setOffAction = nullptr;

// 只有按钮才添加“置ON”和“置OFF”
if (auto btn = dynamic_cast<HmiButton*>(this)) {
setOnAction = menu.addAction("置ON");
setOffAction = menu.addAction("置OFF");

connect(setOnAction, &QAction::triggered, this, [btn]() {
btn->setOn(true);
});

connect(setOffAction, &QAction::triggered, this, [btn]() {
btn->setOn(false);
});
}

menu.addSeparator();

QAction *copyAction = menu.addAction("复制"); QAction *copyAction = menu.addAction("复制");
QAction *deleteAction = menu.addAction("删除"); QAction *deleteAction = menu.addAction("删除");


@@ -278,7 +298,7 @@ QColor HmiComponent::offColor() const {
} }




HmiButton::HmiButton(QGraphicsItem *parent) : HmiComponent(parent)
HmiButton::HmiButton(QGraphicsItem *parent) : HmiComponent(parent), m_isOn(false)
{ {
m_color = Qt::gray; m_color = Qt::gray;
m_offColor = m_color; // OFF状态颜色设为默认颜色 m_offColor = m_color; // OFF状态颜色设为默认颜色
@@ -287,6 +307,23 @@ HmiButton::HmiButton(QGraphicsItem *parent) : HmiComponent(parent)
setColor(m_offColor); // 当前显示OFF颜色 setColor(m_offColor); // 当前显示OFF颜色
} }


bool HmiButton::isOn() const
{
return m_isOn;
}

void HmiButton::setOn(bool on)
{
if (m_isOn != on) {
m_isOn = on;
if (m_isOn)
setColor(m_onColor);
else
setColor(m_offColor);
update();
}
}

QRectF HmiButton::boundingRect() const QRectF HmiButton::boundingRect() const
{ {
return QRectF(0, 0, 65, 30); return QRectF(0, 0, 65, 30);


+ 7
- 0
customgraphics.h View File

@@ -74,8 +74,15 @@ public:
HmiButton(QGraphicsItem *parent = nullptr); HmiButton(QGraphicsItem *parent = nullptr);
QRectF boundingRect() const override; QRectF boundingRect() const override;


// 新增状态标志,true = ON,false = OFF
bool isOn() const;
void setOn(bool on);

protected: protected:
void paintShape(QPainter *painter) override; void paintShape(QPainter *painter) override;

private:
bool m_isOn = false; // 默认OFF
}; };


// 指示灯类 // 指示灯类


+ 108
- 2
hmimodule.cpp View File

@@ -111,6 +111,11 @@ bool HMIModule::saveToFile(const QString& filePath)
compObj["componentName"] = component->componentName(); compObj["componentName"] = component->componentName();
// 新增地址属性 // 新增地址属性
compObj["address"] = component->address(); compObj["address"] = component->address();
// 添加按钮状态
compObj["isOn"] = false; // 默认false
if (auto btn = dynamic_cast<HmiButton*>(component)) {
compObj["isOn"] = btn->isOn();
}


componentsArray.append(compObj); componentsArray.append(compObj);
} }
@@ -136,6 +141,8 @@ bool HMIModule::saveToFile(const QString& filePath)
emit logMessageGenerated(QString("[%1] 保存成功: %2") emit logMessageGenerated(QString("[%1] 保存成功: %2")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")) .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
.arg(filePath)); .arg(filePath));
m_isModified = false;
setModified(false);
return true; return true;
} }


@@ -261,10 +268,18 @@ bool HMIModule::openFromFile(const QString& filePath)
if (offColor.isValid()) if (offColor.isValid())
newItem->setOffColor(offColor); newItem->setOffColor(offColor);


// 恢复 isOn 状态
bool isOn = false;
if (compObj.contains("isOn")) {
isOn = compObj["isOn"].toBool();
}
if (auto btn = dynamic_cast<HmiButton*>(newItem)) {
btn->setOn(isOn);
}

QColor currentColor(colorName); QColor currentColor(colorName);
if (currentColor.isValid()) { if (currentColor.isValid()) {
// 可以根据实际业务逻辑判断,是否恢复为onColor或offColor
// 这里直接恢复当前颜色
// 根据实际业务逻辑判断,是否恢复为onColor或offColor,这里直接恢复当前颜色
newItem->setColor(currentColor); newItem->setColor(currentColor);
} else { } else {
// 如果当前颜色无效,则使用 offColor 作为默认颜色 // 如果当前颜色无效,则使用 offColor 作为默认颜色
@@ -288,9 +303,84 @@ bool HMIModule::openFromFile(const QString& filePath)
emit logMessageGenerated(QString("[%1] 打开文件成功: %2") emit logMessageGenerated(QString("[%1] 打开文件成功: %2")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")) .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
.arg(filePath)); .arg(filePath));
setModified(false);
return true; return true;
} }


void HMIModule::resetPages()
{
QTabWidget* tabWidget = ui_->tabWidget_2;

if (tabWidget->count() == 0) {
// 没有页面,创建第一页
m_pageCount = 1;
m_availablePageNumbers.clear();
m_pageOrder.clear();

QWidget* newPage = new QWidget(tabWidget);
QString pageName = QString("Page 1");
newPage->setObjectName(pageName);

QGraphicsView* newGraphicsView = new QGraphicsView(newPage);
CustomGraphicsScene* newScene = new CustomGraphicsScene(newGraphicsView, this);

QSize defaultSize(691, 381);
newGraphicsView->resize(defaultSize);
newScene->setSceneRect(0, 0, 800, 600);
newGraphicsView->setScene(newScene);

QVBoxLayout* layout = new QVBoxLayout(newPage);
layout->addWidget(newGraphicsView);
newPage->setLayout(layout);

tabWidget->addTab(newPage, pageName);

m_pageOrder.append(1);

connect(newScene, &CustomGraphicsScene::componentCreated, this, &HMIModule::onComponentCreated);
connect(newScene, &CustomGraphicsScene::copyRequestFromScene, this, &HMIModule::onCopyRequested);
connect(newScene, &CustomGraphicsScene::pasteRequestFromScene, this, &HMIModule::onPasteRequested);
connect(newScene, &CustomGraphicsScene::deleteRequestFromScene, this, &HMIModule::onDeleteRequested);

return;
}

// 有页面时:
// 删除除第一页以外的所有页面
while (tabWidget->count() > 1) {
QWidget* page = tabWidget->widget(1);
tabWidget->removeTab(1);
delete page;
}

// 清空第一页场景
QWidget* firstPage = tabWidget->widget(0);
QGraphicsView* view = firstPage->findChild<QGraphicsView*>();
if (view && view->scene()) {
view->scene()->clear();
}

// 重置页面编号管理
m_availablePageNumbers.clear();
m_pageOrder.clear();
m_pageCount = 1;
m_pageOrder.append(1);

// 可以选择更新第一页Tab名称(如果可能被改名)
tabWidget->setTabText(0, "Page 1");
firstPage->setObjectName("Page 1");
}

bool HMIModule::isModified() const
{
return m_isModified;
}

void HMIModule::setModified(bool modified)
{
m_isModified = modified;
}

void HMIModule::setupNewComponent(HmiComponent* item) void HMIModule::setupNewComponent(HmiComponent* item)
{ {
if (!item) return; if (!item) return;
@@ -338,6 +428,7 @@ void HMIModule::prepareToCreateIndicator()
void HMIModule::onComponentCreated(HmiComponent* item) void HMIModule::onComponentCreated(HmiComponent* item)
{ {
setupNewComponent(item); setupNewComponent(item);
setModified(true); // 标记已修改
} }


void HMIModule::onCopyRequested() void HMIModule::onCopyRequested()
@@ -360,6 +451,13 @@ void HMIModule::onCopyRequested()
m_copiedType = ComponentType::Indicator; m_copiedType = ComponentType::Indicator;
} }
m_copiedColor = itemToCopy->color(); m_copiedColor = itemToCopy->color();

// 新增复制以下属性
m_copiedOnColor = itemToCopy->onColor();
m_copiedOffColor = itemToCopy->offColor();
m_copiedComponentName = itemToCopy->componentName();
m_copiedAddress = itemToCopy->address();

m_hasCopiedItem = true; m_hasCopiedItem = true;


emit logMessageGenerated(QString("[%1] 复制组件: %2") emit logMessageGenerated(QString("[%1] 复制组件: %2")
@@ -386,10 +484,15 @@ void HMIModule::onPasteRequested(const QPointF& scenePos)


if (newItem) { if (newItem) {
newItem->setColor(m_copiedColor); newItem->setColor(m_copiedColor);
newItem->setOnColor(m_copiedOnColor);
newItem->setOffColor(m_copiedOffColor);
newItem->setComponentName(m_copiedComponentName);
newItem->setAddress(m_copiedAddress);
newItem->setPos(scenePos); newItem->setPos(scenePos);
currentScene->addItem(newItem); // 使用当前页面的 scene currentScene->addItem(newItem); // 使用当前页面的 scene
setupNewComponent(newItem); setupNewComponent(newItem);
} }
setModified(true); // 内容改变
} }


void HMIModule::onDeleteRequested() void HMIModule::onDeleteRequested()
@@ -412,6 +515,7 @@ void HMIModule::onDeleteRequested()
currentScene->removeItem(item); // 使用当前页面的 scene currentScene->removeItem(item); // 使用当前页面的 scene
delete item; delete item;
} }
setModified(true); // 标记已修改
} }




@@ -533,6 +637,7 @@ void HMIModule::addPage()


// 记录日志 // 记录日志
emit logMessageGenerated(QString("[%1] 添加页面: %2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(pageName)); emit logMessageGenerated(QString("[%1] 添加页面: %2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(pageName));
setModified(true); // 页面变更,标记已修改
} }


// 删除页面的槽函数 // 删除页面的槽函数
@@ -570,6 +675,7 @@ void HMIModule::deletePage()
// 记录日志 // 记录日志
emit logMessageGenerated(QString("[%1] 删除页面: %2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(pageName)); emit logMessageGenerated(QString("[%1] 删除页面: %2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(pageName));
} }
setModified(true); // 标记已修改
} }


// 前一页的槽函数 // 前一页的槽函数


+ 11
- 0
hmimodule.h View File

@@ -17,6 +17,10 @@ public:
void init(); void init();
bool saveToFile(const QString& filePath); bool saveToFile(const QString& filePath);
bool openFromFile(const QString& filePath); bool openFromFile(const QString& filePath);
// 重置页面,清空所有页,只保留一个空的第一页
void resetPages();
bool isModified() const; // 判断是否有未保存的修改
void setModified(bool modified); // 设置修改状态


signals: signals:
void pageAdded(int pageNumber, int index); void pageAdded(int pageNumber, int index);
@@ -48,10 +52,17 @@ private:
CustomGraphicsScene* m_scene; CustomGraphicsScene* m_scene;
ComponentType m_copiedType; ComponentType m_copiedType;
QColor m_copiedColor; QColor m_copiedColor;
// 新增这些成员变量
QColor m_copiedOnColor;
QColor m_copiedOffColor;
QString m_copiedComponentName;
int m_copiedAddress = 0;

bool m_hasCopiedItem = false; // 指示当前是否已经有组件被复制 bool m_hasCopiedItem = false; // 指示当前是否已经有组件被复制
int m_pageCount = 1; // 初始化页面计数器 int m_pageCount = 1; // 初始化页面计数器
QList<int> m_availablePageNumbers; // 存储可用的页面编号 (有序列表) QList<int> m_availablePageNumbers; // 存储可用的页面编号 (有序列表)
QList<int> m_pageOrder; // 维护页面顺序 QList<int> m_pageOrder; // 维护页面顺序
bool m_isModified = false; // 添加一个修改标志变量
}; };


#endif // HMIMODULE_H #endif // HMIMODULE_H

+ 41
- 2
mainwindow.cpp View File

@@ -5,6 +5,7 @@
#include <QButtonGroup> #include <QButtonGroup>
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
#include <QCloseEvent>


MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
@@ -18,8 +19,11 @@ MainWindow::MainWindow(QWidget *parent)
// 连接 HMIModule 的信号到 MainWindow 的槽 // 连接 HMIModule 的信号到 MainWindow 的槽
connect(hmi_, &HMIModule::logMessageGenerated, this, &MainWindow::appendLog); connect(hmi_, &HMIModule::logMessageGenerated, this, &MainWindow::appendLog);


// 新建菜单
connect(ui_->action, &QAction::triggered, this, &MainWindow::onNewFile);

connect(ui_->action_3, &QAction::triggered, this, [this]() { connect(ui_->action_3, &QAction::triggered, this, [this]() {
QString fileName = QFileDialog::getSaveFileName(this, "保存HMI设计", "", "JSON文件 (*.json)");
QString fileName = QFileDialog::getSaveFileName(this, "保存HMI文件", "", "JSON文件 (*.hmi)");
if (!fileName.isEmpty()) { if (!fileName.isEmpty()) {
if (!hmi_->saveToFile(fileName)) { if (!hmi_->saveToFile(fileName)) {
QMessageBox::warning(this, "保存失败", "文件保存失败!"); QMessageBox::warning(this, "保存失败", "文件保存失败!");
@@ -28,7 +32,7 @@ MainWindow::MainWindow(QWidget *parent)
}); });


connect(ui_->action_2, &QAction::triggered, this, [this]() { connect(ui_->action_2, &QAction::triggered, this, [this]() {
QString fileName = QFileDialog::getOpenFileName(this, "打开HMI设计", "", "JSON文件 (*.json)");
QString fileName = QFileDialog::getOpenFileName(this, "打开HMI文件", "", "JSON文件 (*.hmi)");
if (!fileName.isEmpty()) { if (!fileName.isEmpty()) {
if (!hmi_->openFromFile(fileName)) { if (!hmi_->openFromFile(fileName)) {
QMessageBox::warning(this, "打开失败", "文件打开失败或格式不正确!"); QMessageBox::warning(this, "打开失败", "文件打开失败或格式不正确!");
@@ -46,6 +50,8 @@ void MainWindow::initMainWindow()
{ {
setWindowTitle("综合平台编辑器"); setWindowTitle("综合平台编辑器");
setWindowIcon(QIcon(":/resource/image/editor.png")); setWindowIcon(QIcon(":/resource/image/editor.png"));
// 运行默认打开HMI页面
ui_->tabWidget->setCurrentIndex(1);
} }


// 实现槽函数 // 实现槽函数
@@ -53,3 +59,36 @@ void MainWindow::appendLog(const QString& message)
{ {
ui_->textEdit->append(message); ui_->textEdit->append(message);
} }

// 新建菜单动作槽函数
void MainWindow::onNewFile()
{
if (!hmi_)
return;

if (hmi_->isModified()) {
auto ret = QMessageBox::warning(this, "提示",
"当前文件有未保存的更改,是否保存?",
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Save);

if (ret == QMessageBox::Save) {
QString fileName = QFileDialog::getSaveFileName(this, "保存HMI设计", "", "JSON文件 (*.json)");
if (!fileName.isEmpty()) {
if (!hmi_->saveToFile(fileName)) {
QMessageBox::warning(this, "保存失败", "文件保存失败!");
return; // 不新建,保存失败
}
} else {
return; // 取消保存,取消新建
}
} else if (ret == QMessageBox::Cancel) {
return; // 取消新建
}
// 如果是Discard,直接继续新建,丢弃当前修改
}

// 清空编辑区,新建页面
hmi_->resetPages();
}


+ 2
- 1
mainwindow.h View File

@@ -21,12 +21,13 @@ public:
private: private:
void initMainWindow(); void initMainWindow();


// 一个用于接收日志并更新UI的槽函数
private slots: private slots:
void appendLog(const QString& message); void appendLog(const QString& message);
void onNewFile(); // 新增槽函数,处理“新建”菜单


private: private:
Ui::MainWindow *ui_; Ui::MainWindow *ui_;
HMIModule* hmi_; HMIModule* hmi_;
}; };

#endif // MAINWINDOW_H #endif // MAINWINDOW_H

Loading…
Cancel
Save