Selaa lähdekoodia

只有绘图版本,无串口和modbus

main
email 6 tuntia sitten
vanhempi
commit
1f3dffdeba
8 muutettua tiedostoa jossa 21 lisäystä ja 366 poistoa
  1. +19
    -12
      untitled/hmidocument.cpp
  2. +0
    -20
      untitled/mainwindow.cpp
  3. +0
    -4
      untitled/mainwindow.h
  4. +0
    -0
      untitled/modbusmanager.cpp
  5. +0
    -4
      untitled/modbusmanager.h
  6. +0
    -263
      untitled/serialportmanager.cpp
  7. +0
    -57
      untitled/serialportmanager.h
  8. +2
    -6
      untitled/untitled.pro

+ 19
- 12
untitled/hmidocument.cpp Näytä tiedosto

@@ -21,7 +21,7 @@
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include<QSpinBox>
HMIDocument::HMIDocument(QWidget *parent)
: BaseDocument(HMI, parent),
m_title("未命名HMI"),
@@ -269,6 +269,7 @@ void HMIDocument::deleteSelectedItems()
}

// 显示属性对话框
// 在HMIDocument::showItemProperties()方法中替换相关代码
void HMIDocument::showItemProperties()
{
QList<QGraphicsItem*> selectedItems = m_scene->selectedItems();
@@ -283,10 +284,17 @@ void HMIDocument::showItemProperties()
dialog.setWindowTitle("属性设置");
QFormLayout *form = new QFormLayout(&dialog);

// 名称输入 - 使用NamedItem接口
QLineEdit *nameEdit = new QLineEdit(namedItem->name());
// 线圈地址输入 - 使用SpinBox替代LineEdit
QSpinBox *coilAddrSpin = new QSpinBox();
coilAddrSpin->setRange(0, 65535); // 设置PLC线圈地址常见范围
// 尝试从名称解析现有地址(如果之前用数字作为名称)
bool isNumber;
int addr = namedItem->name().toInt(&isNumber);
if (isNumber) {
coilAddrSpin->setValue(addr);
}

// 颜色选择(根据图形类型)
// 颜色选择(保持不变
QColor tempColor1, tempColor2;
QPushButton *colorBtn1 = new QPushButton;
QPushButton *colorBtn2 = new QPushButton;
@@ -303,11 +311,11 @@ void HMIDocument::showItemProperties()
form->addRow("释放颜色:", colorBtn2);
}

// 初始化颜色按钮
// 初始化颜色按钮(保持不变)
colorBtn1->setStyleSheet("background-color:" + tempColor1.name());
colorBtn2->setStyleSheet("background-color:" + tempColor2.name());

// 颜色选择对话框
// 颜色选择对话框(保持不变)
connect(colorBtn1, &QPushButton::clicked, [&]() {
QColor c = QColorDialog::getColor(tempColor1, &dialog);
if (c.isValid()) {
@@ -323,18 +331,18 @@ void HMIDocument::showItemProperties()
}
});

// 布局组装
form->addRow("对象:", nameEdit);
// 布局组装(将名称输入替换为线圈地址)
form->addRow("线圈地址:", coilAddrSpin); // 这里是关键修改
QDialogButtonBox *btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
form->addRow(btnBox);
connect(btnBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
connect(btnBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);

// 应用属性
// 应用属性(使用SpinBox的值作为地址)
if (dialog.exec() == QDialog::Accepted) {
setModified(true);
// 使用NamedItem接口设置名称
namedItem->setName(nameEdit->text());
// 将SpinBox的值转换为字符串保存到名称属性
namedItem->setName(QString::number(coilAddrSpin->value()));

if (auto ellipse = dynamic_cast<ResizableEllipse*>(item)) {
ellipse->setOnColor(tempColor1);
@@ -346,7 +354,6 @@ void HMIDocument::showItemProperties()
item->update();
}
}

// 序列化图形项(用于复制粘贴)
QByteArray HMIDocument::serializeItem(QGraphicsItem *item)
{


+ 0
- 20
untitled/mainwindow.cpp Näytä tiedosto

@@ -204,31 +204,11 @@ void MainWindow::createMenus()
QMenu *simulationMenu = menuBar()->addMenu("仿真");
simulationMenu->setFont(itemFont);

// 连接动作
QAction *connectAction = new QAction("连接设置", this);
connectAction->setFont(itemFont);
connect(connectAction, &QAction::triggered, this, &MainWindow::onConnectClicked);
simulationMenu->addAction(connectAction);

// 运行动作 (暂时留空)
QAction *runAction = new QAction("运行", this);
runAction->setFont(itemFont);
runAction->setEnabled(false);
simulationMenu->addAction(runAction);

}
void MainWindow::onConnectClicked()
{
if (!m_serialDialog) {
m_serialDialog = new SerialPortManager(this);
connect(m_serialDialog, &SerialPortManager::logMessage,this, &MainWindow::handleSerialLog);
}

m_serialDialog->exec();
}
void MainWindow::handleSerialLog(const QString &message)
{
m_logEdit->append(message);
}
// 创建左侧工具栏
void MainWindow::createToolbars()


+ 0
- 4
untitled/mainwindow.h Näytä tiedosto

@@ -7,7 +7,6 @@
#include <QAction>
#include<QTextEdit>
#include "basedocument.h"
#include "serialportmanager.h"
#include<QPushButton>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
@@ -34,10 +33,7 @@ private slots:
void onCloseTab(int index); // 关闭标签页
void onClearLogButtonClicked();
void showLogContextMenu(const QPoint &pos);
void onConnectClicked(); // 连接菜单项槽函数
void handleSerialLog(const QString &message);
private:
SerialPortManager *m_serialDialog=nullptr; // 串口对话框
void createMenus(); // 创建菜单栏
QWidget* m_logPanelContainer;
QDockWidget* m_logDock;


+ 0
- 0
untitled/modbusmanager.cpp Näytä tiedosto


+ 0
- 4
untitled/modbusmanager.h Näytä tiedosto

@@ -1,4 +0,0 @@
#ifndef MODBUSMANAGER_H
#define MODBUSMANAGER_H

#endif // MODBUSMANAGER_H

+ 0
- 263
untitled/serialportmanager.cpp Näytä tiedosto

@@ -1,263 +0,0 @@
#include "serialportmanager.h"
#include <QSerialPortInfo>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGroupBox>
#include <QMessageBox>
#include <QDebug>

SerialPortManager::SerialPortManager(QWidget *parent)
: QDialog(parent), m_serial(new QSerialPort(this))
{
setWindowTitle("串口连接设置");
setFixedSize(450,200);

// 连接串口信号
connect(m_serial, &QSerialPort::readyRead, this, &SerialPortManager::handleReadyRead);
connect(m_serial, &QSerialPort::errorOccurred, this, &SerialPortManager::handleError);

// 主布局
QVBoxLayout *mainLayout = new QVBoxLayout(this);

// 创建单个GroupBox - 串口参数设置
QGroupBox *settingsGroup = new QGroupBox("串口参数设置", this);
QFormLayout *formLayout = new QFormLayout(settingsGroup);

// 串口选择行
m_portComboBox = new QComboBox(this);
QPushButton *refreshButton = new QPushButton("刷新", this);
QHBoxLayout *portComboLayout = new QHBoxLayout;
portComboLayout->addWidget(m_portComboBox, 5);
portComboLayout->addWidget(refreshButton, 1);
formLayout->addRow("串口:", portComboLayout);

// 波特率选择行
m_baudComboBox = new QComboBox(this);
populateBaudRates();
formLayout->addRow("波特率:", m_baudComboBox);

// 奇偶校验选择行
m_parityComboBox = new QComboBox(this);
populateParities();
formLayout->addRow("奇偶校验:", m_parityComboBox);

// 从站地址行
m_stationSpinBox = new QSpinBox(this);
m_stationSpinBox->setRange(1, 247);
m_stationSpinBox->setValue(1);
formLayout->addRow("从站地址:", m_stationSpinBox);

// 添加到主布局
mainLayout->addWidget(settingsGroup);

// 按钮区域
QHBoxLayout *buttonLayout = new QHBoxLayout;
m_connectBtn = new QPushButton("连接", this);
QPushButton *cancelButton = new QPushButton("取消", this);

// 状态标签
m_statusLabel = new QLabel("状态: 未连接", this);
m_statusLabel->setStyleSheet("QLabel { color: red; }");

buttonLayout->addWidget(m_statusLabel);
buttonLayout->addStretch();
buttonLayout->addWidget(m_connectBtn);
buttonLayout->addWidget(cancelButton);

// 添加到主布局
mainLayout->addLayout(buttonLayout);

// 连接信号
connect(refreshButton, &QPushButton::clicked, this, &SerialPortManager::refreshPorts);
connect(m_connectBtn, &QPushButton::clicked, this, &SerialPortManager::onConnectClicked);
connect(cancelButton, &QPushButton::clicked, this, &QDialog::reject);

// 初始刷新端口
refreshPorts();
}

SerialPortManager::~SerialPortManager()
{
if (m_serial->isOpen()) {
m_serial->close();
}
}

// 串口操作接口实现
bool SerialPortManager::isOpen() const
{
return m_serial->isOpen();
}

void SerialPortManager::openSerialPort()
{
if (!m_serial->isOpen()) {
onConnectClicked();
}
}

void SerialPortManager::closeSerialPort()
{
if (m_serial->isOpen()) {
m_serial->close();
updateConnectionState(false);
}
}

QByteArray SerialPortManager::readAll()
{
return m_serial->readAll();
}

void SerialPortManager::write(const QByteArray &data)
{
if (m_serial->isOpen()) {
m_serial->write(data);
}
}

// 连接按钮槽函数
void SerialPortManager::onConnectClicked()
{
if (m_serial->isOpen()) {
// 如果已连接,则断开
m_serial->close();
updateConnectionState(false);
return;
}

// 获取配置
QString portName = m_portComboBox->currentData().toString();
int baudRate = m_baudComboBox->currentData().toInt();
QSerialPort::Parity parity = static_cast<QSerialPort::Parity>(m_parityComboBox->currentData().toInt());

if (portName.isEmpty()) {
QMessageBox::warning(this, "错误", "请选择有效的串口");
return;
}

// 配置串口
m_serial->setPortName(portName);
m_serial->setBaudRate(baudRate);
m_serial->setDataBits(QSerialPort::Data8);
m_serial->setParity(parity);
m_serial->setStopBits(QSerialPort::OneStop);

if (m_serial->open(QIODevice::ReadWrite))
{
updateConnectionState(true);
QString logMsg = QString("串口连接成功: %1, %2 bps, 从站地址: %3")
.arg(portName)
.arg(baudRate)
.arg(m_stationSpinBox->value());
emit logMessage(logMsg); // 发送统一日志
}
else
{
QString errorMsg = QString("串口连接失败: %1").arg(m_serial->errorString());
emit logMessage(errorMsg); // 发送统一日志
}

}

// 更新连接状态
void SerialPortManager::updateConnectionState(bool connected)
{
if (connected) {
m_connectBtn->setText("断开");
m_statusLabel->setText("状态: 已连接");
m_statusLabel->setStyleSheet("QLabel { color: green; }");
} else {
m_connectBtn->setText("连接");
m_statusLabel->setText("状态: 未连接");
m_statusLabel->setStyleSheet("QLabel { color: red; }");
}
}

// 数据接收处理
void SerialPortManager::handleReadyRead()
{
QByteArray data = m_serial->readAll();
if (!data.isEmpty()) {
QString hexString = data.toHex().toUpper(); // 转换为大写的十六进制
emit logMessage("接收: " + hexString); // 发送统一日志
}

}

// 错误处理
void SerialPortManager::handleError(QSerialPort::SerialPortError error)
{
if (error != QSerialPort::NoError)
{
QString errorMsg = QString("串口错误: %1").arg(m_serial->errorString());
emit logMessage(errorMsg); // 发送统一日志
}
}

void SerialPortManager::populateBaudRates()
{
m_baudComboBox->clear();
m_baudComboBox->addItem("4800", QSerialPort::Baud4800);
m_baudComboBox->addItem("9600", QSerialPort::Baud9600);
m_baudComboBox->addItem("19200", QSerialPort::Baud19200);
m_baudComboBox->addItem("38400", QSerialPort::Baud38400);
m_baudComboBox->addItem("57600", QSerialPort::Baud57600);
m_baudComboBox->addItem("115200", QSerialPort::Baud115200);
m_baudComboBox->setCurrentIndex(1); // 默认9600
}

void SerialPortManager::populateParities()
{
m_parityComboBox->clear();
m_parityComboBox->addItem("无校验", QSerialPort::NoParity);
m_parityComboBox->addItem("奇校验", QSerialPort::OddParity);
m_parityComboBox->addItem("偶校验", QSerialPort::EvenParity);
m_parityComboBox->setCurrentIndex(0); // 默认无校验
}

void SerialPortManager::refreshPorts()
{
m_portComboBox->clear();
const auto ports = QSerialPortInfo::availablePorts();

for (const QSerialPortInfo &port : ports) {
QString description = port.description();
if (description.isEmpty()) description = "未知设备";

QString itemText = QString("%1 (%2)")
.arg(port.portName())
.arg(description);

m_portComboBox->addItem(itemText, port.portName());
}
if (ports.isEmpty())
{
m_portComboBox->addItem("无可用端口", "");
}
}

QString SerialPortManager::portName() const
{
return m_portComboBox->currentData().toString();
}

int SerialPortManager::baudRate() const
{
return m_baudComboBox->currentData().toInt();
}

QSerialPort::Parity SerialPortManager::parity() const
{
return static_cast<QSerialPort::Parity>(m_parityComboBox->currentData().toInt());
}

QSerialPort::StopBits SerialPortManager::stopBits() const
{
return QSerialPort::OneStop;
}

int SerialPortManager::stationAddress() const
{
return m_stationSpinBox->value();
}

+ 0
- 57
untitled/serialportmanager.h Näytä tiedosto

@@ -1,57 +0,0 @@
#ifndef SERIALPORTMANAGER_H
#define SERIALPORTMANAGER_H

#include <QDialog>
#include <QSerialPort>
#include <QComboBox>
#include <QPushButton>
#include <QFormLayout>
#include <QSpinBox>
#include <QLabel>

class SerialPortManager : public QDialog
{
Q_OBJECT
public:
explicit SerialPortManager(QWidget *parent = nullptr);
~SerialPortManager();

// 获取串口配置
QString portName() const;
int baudRate() const;
QSerialPort::Parity parity() const;
QSerialPort::StopBits stopBits() const;
int stationAddress() const;

// 新增串口操作接口
bool isOpen() const;
void openSerialPort();
void closeSerialPort();
QByteArray readAll();
void write(const QByteArray &data);

signals:
void errorOccurred(const QString &error);
void logMessage(const QString &message);

private slots:
void refreshPorts();
void onConnectClicked();
void handleReadyRead();
void handleError(QSerialPort::SerialPortError error);

private:
void populateBaudRates();
void populateParities();
void updateConnectionState(bool connected);

QSerialPort *m_serial; // 串口对象
QComboBox *m_portComboBox;
QComboBox *m_baudComboBox;
QComboBox *m_parityComboBox;
QSpinBox *m_stationSpinBox;
QPushButton *m_connectBtn; // 连接/断开按钮
QLabel *m_statusLabel; // 状态标签
};

#endif // SERIALPORTMANAGER_H

+ 2
- 6
untitled/untitled.pro Näytä tiedosto

@@ -21,20 +21,16 @@ SOURCES += \
hmidocument.cpp \
main.cpp \
mainwindow.cpp \
modbusmanager.cpp \
plcdocument.cpp \
plcitems.cpp \
serialportmanager.cpp
plcitems.cpp

HEADERS += \
basedocument.h \
graphicsitems.h \
hmidocument.h \
mainwindow.h \
modbusmanager.h \
plcdocument.h \
plcitems.h \
serialportmanager.h
plcitems.h

FORMS += \
mainwindow.ui


Ladataan…
Peruuta
Tallenna