diff --git a/untitled/mainwindow.cpp b/untitled/mainwindow.cpp index 6ed1bc7..3988f3d 100644 --- a/untitled/mainwindow.cpp +++ b/untitled/mainwindow.cpp @@ -24,34 +24,27 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setWindowTitle("综合平台编程器"); - setGeometry(500, 200, 1000, 700); - - // 1. 先创建中央区域 - QWidget* centralContainer = new QWidget; - QHBoxLayout* centralLayout = new QHBoxLayout(centralContainer); - centralLayout->setContentsMargins(0, 0, 0, 0); - - // 2. 左侧工具栏区 - createToolbars(); // 创建工具栏对象 - centralLayout->addWidget(m_leftToolBar); - - // 3. 中央文档区 - m_tabWidget = new QTabWidget; - m_tabWidget->setTabsClosable(true); - centralLayout->addWidget(m_tabWidget, 1); // 占据剩余空间 - - // 4. 设置中央部件 - setCentralWidget(centralContainer); - - // 5. 创建日志面板 - createLogPanel(); - - // 连接信号 - connect(m_tabWidget, &QTabWidget::currentChanged, this, &MainWindow::onTabChanged); - connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, &MainWindow::onCloseTab); - - // 创建菜单 - createMenus(); + setGeometry(500, 200, 1000, 700); + // 1. 先创建中央区域 + QWidget* centralContainer = new QWidget; + QHBoxLayout* centralLayout = new QHBoxLayout(centralContainer); + centralLayout->setContentsMargins(0, 0, 0, 0); + // 2. 左侧工具栏区 + createToolbars(); // 创建工具栏对象 + centralLayout->addWidget(m_leftToolBar); + // 3. 中央文档区 + m_tabWidget = new QTabWidget; + m_tabWidget->setTabsClosable(true); + centralLayout->addWidget(m_tabWidget, 1); // 占据剩余空间 + // 4. 设置中央部件 + setCentralWidget(centralContainer); + // 5. 创建日志面板 + createLogPanel(); + // 连接信号 + connect(m_tabWidget, &QTabWidget::currentChanged, this, &MainWindow::onTabChanged); + connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, &MainWindow::onCloseTab); + // 创建菜单 + createMenus(); } MainWindow::~MainWindow() @@ -206,8 +199,37 @@ void MainWindow::createMenus() editMenu->addAction(copyAction); editMenu->addAction(pasteAction); editMenu->addAction(deleteAction); + + // 添加仿真菜单项 + 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() { diff --git a/untitled/mainwindow.h b/untitled/mainwindow.h index 64422dc..c0f591d 100644 --- a/untitled/mainwindow.h +++ b/untitled/mainwindow.h @@ -7,6 +7,7 @@ #include #include #include "basedocument.h" +#include "serialportmanager.h" #include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } @@ -33,7 +34,10 @@ 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; diff --git a/untitled/modbusmanager.cpp b/untitled/modbusmanager.cpp new file mode 100644 index 0000000..e69de29 diff --git a/untitled/modbusmanager.h b/untitled/modbusmanager.h new file mode 100644 index 0000000..c2e4bfc --- /dev/null +++ b/untitled/modbusmanager.h @@ -0,0 +1,4 @@ +#ifndef MODBUSMANAGER_H +#define MODBUSMANAGER_H + +#endif // MODBUSMANAGER_H diff --git a/untitled/serialportmanager.cpp b/untitled/serialportmanager.cpp new file mode 100644 index 0000000..0de7e1e --- /dev/null +++ b/untitled/serialportmanager.cpp @@ -0,0 +1,263 @@ +#include "serialportmanager.h" +#include +#include +#include +#include +#include +#include + +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(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(m_parityComboBox->currentData().toInt()); +} + +QSerialPort::StopBits SerialPortManager::stopBits() const +{ + return QSerialPort::OneStop; +} + +int SerialPortManager::stationAddress() const +{ + return m_stationSpinBox->value(); +} diff --git a/untitled/serialportmanager.h b/untitled/serialportmanager.h new file mode 100644 index 0000000..0f937e3 --- /dev/null +++ b/untitled/serialportmanager.h @@ -0,0 +1,57 @@ +#ifndef SERIALPORTMANAGER_H +#define SERIALPORTMANAGER_H + +#include +#include +#include +#include +#include +#include +#include + +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 diff --git a/untitled/untitled.pro b/untitled/untitled.pro index eaebac4..b670073 100644 --- a/untitled/untitled.pro +++ b/untitled/untitled.pro @@ -1,5 +1,5 @@ QT += core gui - +QT += core gui widgets serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++11 @@ -21,16 +21,20 @@ SOURCES += \ hmidocument.cpp \ main.cpp \ mainwindow.cpp \ + modbusmanager.cpp \ plcdocument.cpp \ - plcitems.cpp + plcitems.cpp \ + serialportmanager.cpp HEADERS += \ basedocument.h \ graphicsitems.h \ hmidocument.h \ mainwindow.h \ + modbusmanager.h \ plcdocument.h \ - plcitems.h + plcitems.h \ + serialportmanager.h FORMS += \ mainwindow.ui