Qt+C++串口调试接收发送数据曲线图

这篇具有很好参考价值的文章主要介绍了Qt+C++串口调试接收发送数据曲线图。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

程序示例精选

Qt+C++串口调试接收发送数据曲线图

如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助!

前言

这篇博客针对<<Qt+C++串口调试接收发送数据曲线图>>编写代码,代码整洁,规则,易读。 学习与应用推荐首选。


文章目录

一、所需工具软件

二、使用步骤

        1. 引入库

        2. 代码实现

        3. 运行结果

三、在线协助

一、所需工具软件

1. VS, Qt

2. C++

二、使用步骤

1.引入库

#include <QAction>
#include <QCheckBox>
#include <QDragEnterEvent>
#include <QDebug>
#include <QLineEdit>
#include <QMenu>
#include <QMenuBar>
#include <QtSerialPort/QSerialPort>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QGroupBox>
#include <QTextBrowser>
#include <QtWidgets/QFileDialog>
#include <QTimer>
#include <QtCore/QSettings>
#include <QtCore/QProcess>
#include <QStatusBar>
#include <QSplitter>
#include <data/SerialReadWriter.h>
#include <data/TcpServerReadWriter.h>
#include <data/TcpClientReadWriter.h>
#include <QRadioButton>
#include <QButtonGroup>
#include <data/BridgeReadWriter.h>
#include <QMimeData>
#include <QtSerialPort/QSerialPortInfo>
#include <data/SerialBridgeReadWriter.h>
#include <utils/FileUtil.h>
#include <QTextCodec>

2. 代码实现

代码如下:

void MainWindow::openReadWriter() {
    if (_readWriter != nullptr) {
        _readWriter->close();
        delete _readWriter;
        _readWriter = nullptr;
        emit serialStateChanged(false);
    }

    bool result;

    if (readWriterButtonGroup->checkedButton() == serialRadioButton) {
        _serialType = SerialType::Normal;
        auto settings = new SerialSettings();
        settings->name = serialPortNameComboBox->currentText();
        settings->baudRate = serialPortBaudRateComboBox->currentText().toInt();

        settings->dataBits = (QSerialPort::DataBits) serialPortDataBitsComboBox->currentText().toInt();
        settings->stopBits = (QSerialPort::StopBits) serialPortStopBitsComboBox->currentData().toInt();
        settings->parity = (QSerialPort::Parity) serialPortParityComboBox->currentData().toInt();
        auto readWriter = new SerialReadWriter(this);
        readWriter->setSerialSettings(*settings);
        qDebug() << settings->name << settings->baudRate << settings->dataBits << settings->stopBits
                 << settings->parity;
        result = readWriter->open();
        if (!result) {
            showWarning(tr("消息"), tr("串口被占用或者不存在"));
            return;
        }
        _readWriter = readWriter;
        _serialType = SerialType::Normal;
    } else if (readWriterButtonGroup->checkedButton() == tcpServerRadioButton) {
        _serialType = SerialType::TcpServer;
        auto address = tcpAddressLineEdit->text();
        bool ok;
        auto port = tcpPortLineEdit->text().toInt(&ok);
        if (!ok) {
            showMessage("", tr("端口格式不正确"));
            return;
        }

        auto readWriter = new TcpServerReadWriter(this);
        readWriter->
                setAddress(address);
        readWriter->
                setPort(port);
        qDebug() << address << port;
        result = readWriter->open();
        if (!result) {
            showWarning("", tr("建立服务器失败"));
            return;
        }
        connect(readWriter, &TcpServerReadWriter::currentSocketChanged, this, &MainWindow::updateTcpClient);
        connect(readWriter, &TcpServerReadWriter::connectionClosed, this, &MainWindow::clearTcpClient);
        _readWriter = readWriter;
    } else if (readWriterButtonGroup->checkedButton() == tcpClientRadioButton) {
        _serialType = SerialType::TcpClient;
        auto address = tcpAddressLineEdit->text();
        bool ok;
        auto port = tcpPortLineEdit->text().toInt(&ok);
        if (!ok) {
            showMessage("", tr("端口格式不正确"));
            return;
        }

        auto readWriter = new TcpClientReadWriter(this);
        readWriter->setAddress(address);
        readWriter->setPort(port);

        qDebug() << address << port;
        result = readWriter->open();
        if (!result) {
            showError("", tr("连接服务器失败"));
            return;
        }
        _readWriter = readWriter;
    } else if (readWriterButtonGroup->checkedButton() == serialBridgeRadioButton) {
        _serialType = SerialType::SerialBridge;

        auto settings1 = new SerialSettings();
        settings1->name = serialPortNameComboBox->currentText();
        settings1->baudRate = serialPortBaudRateComboBox->currentText().toInt();

        settings1->dataBits = (QSerialPort::DataBits) serialPortDataBitsComboBox->currentText().toInt();
        settings1->stopBits = (QSerialPort::StopBits) serialPortStopBitsComboBox->currentData().toInt();
        settings1->parity = (QSerialPort::Parity) serialPortParityComboBox->currentData().toInt();

        auto settings2 = new SerialSettings();
        settings2->name = secondSerialPortNameComboBox->currentText();
        settings2->baudRate = secondSerialPortBaudRateComboBox->currentText().toInt();

        settings2->dataBits = (QSerialPort::DataBits) secondSerialPortDataBitsComboBox->currentText().toInt();
        settings2->stopBits = (QSerialPort::StopBits) secondSerialPortStopBitsComboBox->currentText().toInt();
        settings2->parity = (QSerialPort::Parity) secondSerialPortParityComboBox->currentText().toInt();

        auto readWriter = new SerialBridgeReadWriter(this);

        readWriter->setSettings(*settings1, *settings2);
        result = readWriter->open();
        if (!result) {
            showWarning(tr("消息"), QString(tr("串口被占用或者不存在,%1")).arg(readWriter->settingsText()));
            return;
        }

        connect(readWriter, &SerialBridgeReadWriter::serial1DataRead, [this](const QByteArray &data) {
            showSendData(data);
        });

        connect(readWriter, &SerialBridgeReadWriter::serial2DataRead, [this](const QByteArray &data) {
            showReadData(data);
        });

        _readWriter = readWriter;
    } else {
        _serialType = SerialType::Bridge;
        auto settings = new SerialSettings();
        settings->name = serialPortNameComboBox->currentText();
        settings->baudRate = serialPortBaudRateComboBox->currentText().toInt();

        settings->dataBits = (QSerialPort::DataBits) serialPortDataBitsComboBox->currentText().toInt();
        settings->stopBits = (QSerialPort::StopBits) serialPortStopBitsComboBox->currentData().toInt();
        settings->parity = (QSerialPort::Parity) serialPortParityComboBox->currentData().toInt();

        auto address = tcpAddressLineEdit->text();
        bool ok;
        auto port = tcpPortLineEdit->text().toInt(&ok);
        if (!ok) {
            showMessage("", tr("端口格式不正确"));
            return;
        }

        auto readWriter = new BridgeReadWriter(this);

        readWriter->setSettings(*settings, address, static_cast<qint16>(port));
        result = readWriter->open();
        if (!result) {
            showWarning(tr("消息"), tr("串口被占用或者不存在"));
            return;
        }

        connect(readWriter, &BridgeReadWriter::currentSocketChanged,
                this, &MainWindow::updateTcpClient);
        connect(readWriter, &BridgeReadWriter::connectionClosed,
                this, &MainWindow::clearTcpClient);
        connect(readWriter, &BridgeReadWriter::serialDataRead, [this](const QByteArray &data) {
            showSendData(data);
        });
        connect(readWriter, &BridgeReadWriter::tcpDataRead, [this](const QByteArray &data) {
            showReadData(data);
        });

        _readWriter = readWriter;
    }
    connect(_readWriter, &AbstractReadWriter::readyRead,
            this, &MainWindow::readData);


    emit serialStateChanged(result);
}

void MainWindow::closeReadWriter() {
    stopAutoSend();
    if (_readWriter != nullptr) {
        _readWriter->close();
        delete _readWriter;
        _readWriter = nullptr;
    }
    emit serialStateChanged(false);
}

void MainWindow::createConnect() {

    connect(readWriterButtonGroup, QOverload<QAbstractButton *, bool>::of(&QButtonGroup::buttonToggled),
            [=](QAbstractButton *button, bool checked) {
                if (checked && isReadWriterOpen()) {
                    SerialType serialType;
                    if (button == tcpServerRadioButton) {
                        serialType = SerialType::TcpServer;
                    } else if (button == tcpClientRadioButton) {
                        serialType = SerialType::TcpClient;
                    } else if (button == bridgeRadioButton) {
                        serialType = SerialType::Bridge;
                    } else {
                        serialType = SerialType::Normal;
                    }

                    if (serialType != _serialType) {
                        if (showWarning("", tr("串口配置已经改变,是否重新打开串口?"))) {
                            openReadWriter();
                        }
                    }
                }
            });

    connect(this, &MainWindow::serialStateChanged, [this](bool isOpen) {
        setOpenButtonText(isOpen);
        QString stateText;
        if (isOpen) {
            stateText = QString(tr("串口打开成功,%1")).arg(_readWriter->settingsText());
        } else {
            stateText = QString(tr("串口关闭"));
        }
        skipSendCount = 0;
        updateStatusMessage(stateText);
    });

    connect(this, &MainWindow::readBytesChanged, this, &MainWindow::updateReadBytes);
    connect(this, &MainWindow::writeBytesChanged, this, &MainWindow::updateWriteBytes);
    connect(this, &MainWindow::currentWriteCountChanged, this, &MainWindow::updateCurrentWriteCount);

    connect(openSerialButton, &QPushButton::clicked, [=](bool value) {
        if (!isReadWriterOpen()) {
            openReadWriter();
        } else {
            closeReadWriter();
        }
    });

    connect(refreshSerialButton, &QPushButton::clicked, [=] {
        _dirty = true;
        updateSerialPortNames();
    });

    connect(saveReceiveDataButton, &QPushButton::clicked, this, &MainWindow::saveReceivedData);
    connect(clearReceiveDataButton, &QPushButton::clicked, this, &MainWindow::clearReceivedData);

    connect(saveSentDataButton, &QPushButton::clicked, this, &MainWindow::saveSentData);
    connect(clearSentDataButton, &QPushButton::clicked, this, &MainWindow::clearSentData);

    connect(autoSendCheckBox, &QCheckBox::clicked, [this] {
        autoSendTimer->stop();
    });

    connect(loopSendCheckBox, &QCheckBox::stateChanged, [this] {
        _loopSend = loopSendCheckBox->isChecked();
    });

    connect(resetLoopSendButton, &QPushButton::clicked, [this] {
        skipSendCount = 0;
        serialController->setCurrentCount(0);
        emit currentWriteCountChanged(0);
    });

    connect(currentSendCountLineEdit, &QLineEdit::editingFinished, [this] {
        bool ok;
        auto newCount = currentSendCountLineEdit->text().toInt(&ok);
        if (ok) {
            serialController->setCurrentCount(newCount);
        } else {
            currentSendCountLineEdit->setText(QString::number(serialController->getCurrentCount()));
        }
    });

    connect(sendLineButton, &QPushButton::clicked, [this] {
        if (!isReadWriterConnected()) {
            handlerSerialNotOpen();
            return;
        }

        if (autoSendState == AutoSendState::Sending) {
            stopAutoSend();
        } else {
            if (_dirty) {
                _dirty = false;
                _sendType = SendType::Line;
                updateSendData(hexCheckBox->isChecked(), sendTextEdit->toPlainText());
                updateSendType();
            }
            sendNextData();
            startAutoSendTimerIfNeed();
        }

        if (autoSendState == AutoSendState::Sending) {
            sendLineButton->setText(tr("停止"));
        } else {
            resetSendButtonText();
        }
    });

    connect(processTextButton, &QPushButton::clicked, [this] {
        openDataProcessDialog(sendTextEdit->toPlainText());
    });

    connect(clearTextButton, &QPushButton::clicked, [this]{
       sendTextEdit->clear();
    });

    connect(lineReturnButtonGroup, QOverload<QAbstractButton *, bool>::of(&QButtonGroup::buttonToggled),
            [=](QAbstractButton *button, bool checked) {
                if (checked) {
                    if (button == sendRReturnLineButton) {
                        lineReturn = QByteArray("\r");
                    } else if (button == sendNReturnLineButton) {
                        lineReturn = QByteArray("\n");
                    } else {
                        lineReturn = QByteArray("\r\n");
                    }
                }
            });

    connect(autoSendTimer, &QTimer::timeout,
            [this] {
                sendNextData();
            });
    connect(hexCheckBox, &QCheckBox::stateChanged, [this] {
        this->_dirty = true;
    });

    connect(sendTextEdit, &QTextEdit::textChanged, [this] {
        this->_dirty = true;
    });
}

void MainWindow::setOpenButtonText(bool isOpen) {
    if (isOpen) {
        openSerialButton->setText(tr("关闭"));
    } else {
        openSerialButton->setText("打开");
    }
}

void MainWindow::createActions() {
    openAct = new QAction(tr("&打开(&O)"), this);
    openAct->setShortcut(QKeySequence::Open);
    openAct->setStatusTip(tr("打开一个文件"));
    connect(openAct, &QAction::triggered, this, &MainWindow::open);

    saveAct = new QAction(tr("&保存(&S)"), this);
    saveAct->setShortcut(QKeySequence::Save);
    saveAct->setStatusTip(tr("保存一个文件"));
    connect(saveAct, &QAction::triggered, this, &MainWindow::save);

    validateDataAct = new QAction(tr("计算校验(&E)"), this);
    validateDataAct->setShortcut(tr("Ctrl+E"));
    validateDataAct->setStatusTip(tr("计算数据校验值"));
    connect(validateDataAct, &QAction::triggered, this, &MainWindow::openDataValidator);

    convertDataAct = new QAction(tr("数据转换(&T)"));
    convertDataAct->setShortcut(tr("Ctrl+T"));
    convertDataAct->setStatusTip(tr("数据转换"));
    connect(convertDataAct, &QAction::triggered, this, &MainWindow::openConvertDataDialog);

    dataProcessAct = new QAction(tr("数据处理(&P)"));
    dataProcessAct->setShortcut(tr("Ctrl+P"));
    dataProcessAct->setStatusTip(tr("数据处理"));
    connect(dataProcessAct, &QAction::triggered, [this] {
        openDataProcessDialog("");
    });
}

void MainWindow::createMenu() {
    fileMenu = menuBar()->addMenu(tr("文件(&F)"));
    fileMenu->addAction(openAct);
    fileMenu->addAction(saveAct);

    toolMenu = menuBar()->addMenu(tr("工具(&T)"));
    toolMenu->addAction(validateDataAct);
    toolMenu->addAction(convertDataAct);
    toolMenu->addAction(dataProcessAct);
}

void MainWindow::open() {
    auto lastDir = runConfig->lastDir;
    QString fileName = QFileDialog::getOpenFileName(this, tr("打开数据文件"), lastDir, "");
    if (fileName.isEmpty()) {
        return;
    }

    QFile file(fileName);
    if (file.open(QIODevice::ReadOnly)) {
        runConfig->lastDir = getFileDir(fileName);
        auto data = file.readAll();
        sendTextEdit->setText(QString::fromLocal8Bit(data));
    }
}

void MainWindow::save() {
    saveReceivedData();
}

void MainWindow::openDataValidator() {
    CalculateCheckSumDialog dialog(this);
    dialog.setModal(true);
    dialog.exec();
}

void MainWindow::openConvertDataDialog() {
    ConvertDataDialog dialog(this);
    dialog.setModal(true);
    dialog.exec();
}

void MainWindow::openDataProcessDialog(const QString &text) {
    DataProcessDialog dialog(text, this);
    dialog.setModal(true);

    int result = dialog.exec();
    if (result == QDialog::Accepted) {
        sendTextEdit->setText(dialog.text());
    }
}

void MainWindow::displayReceiveData(const QByteArray &data) {

    if (pauseReceiveCheckBox->isChecked()) {
        return;
    }

    static QString s;

    s.clear();

    if (addReceiveTimestampCheckBox->isChecked()) {
        s.append("[").append(getTimestamp()).append("] ");
    }

    if (!s.isEmpty()) {
        s.append(" ");
    }
    if (displayReceiveDataAsHexCheckBox->isChecked()) {
        s.append(dataToHex(data));
    } else {
        s.append(QString::fromLocal8Bit(data));
    }

    if (addLineReturnCheckBox->isChecked() || addReceiveTimestampCheckBox->isChecked()) {
        receiveDataBrowser->append(s);
    } else {
        auto text = receiveDataBrowser->toPlainText();
        text.append(s);
        receiveDataBrowser->setText(text);
        receiveDataBrowser->moveCursor(QTextCursor::End);
    }
}

void MainWindow::displaySentData(const QByteArray &data) {
    if (displaySendDataAsHexCheckBox->isChecked()) {
        sendDataBrowser->append(dataToHex(data));
    } else {
        sendDataBrowser->append(QString::fromLocal8Bit(data));
    }
}

void MainWindow::sendNextData() {
    if (isReadWriterConnected()) {
        if (skipSendCount > 0) {
            auto delay = skipSendCount * sendIntervalLineEdit->text().toInt();
            updateStatusMessage(QString("%1毫秒后发送下一行").arg(delay));
            skipSendCount--;
            return;
        }

        qDebug() << "sendNextData readEnd:" << serialController->readEnd() << "current:"
                 << serialController->getCurrentCount();
        if (!_loopSend && autoSendCheckBox->isChecked() && serialController->readEnd()) {
            serialController->setCurrentCount(0);
            stopAutoSend();
            return;
        }
        auto data = serialController->readNextFrame();
        if (data.isEmpty()) {
            updateStatusMessage(tr("空行,不发送"));
            if (autoSendCheckBox->isChecked()) {
                auto emptyDelay = emptyLineDelayLindEdit->text().toInt();
                auto sendInterval = sendIntervalLineEdit->text().toInt();
                if (emptyDelay > sendInterval) {
                    skipSendCount = emptyDelay / sendInterval;
                    if (emptyDelay % sendInterval != 0) {
                        skipSendCount += 1;
                    }
                    skipSendCount--;
                    updateStatusMessage(QString(tr("空行,%1毫秒后发送下一行")).arg(emptyDelay));
                }
            }
            emit currentWriteCountChanged(serialController->getCurrentCount());
            return;
        }
        writeData(data);
        if (sendLineReturnCheckBox->isChecked()) {
            writeData(lineReturn);
        }
        if (hexCheckBox->isChecked()) {
            updateStatusMessage(QString(tr("发送 %1")).arg(QString(dataToHex(data))));
        } else {
            updateStatusMessage(QString(tr("发送 %1")).arg(QString(data)));
        }
        emit currentWriteCountChanged(serialController->getCurrentCount());
    } else {
        handlerSerialNotOpen();
    }
}

void MainWindow::updateSendData(bool isHex, const QString &text) {
    if (serialController != nullptr) {
        QStringList lines = getLines(text);
        QList<QByteArray> dataList;
        if (isHex) {
            for (auto &line :lines) {
                dataList << dataFromHex(line);
            }
        } else {
            for (auto &line:lines) {
                dataList << line.toLocal8Bit();
            }
        }
        serialController->setData(dataList);
        totalSendCount = serialController->getTotalCount();
        updateTotalSendCount(totalSendCount);
    }
}

void MainWindow::readSettings() {

    qDebug() << "readSettings";

    updateSerialPortNames();

    QSettings settings("Zhou Jinlong", "Serial Wizard");

    settings.beginGroup("Basic");
    auto serialType = SerialType(settings.value("serial_type", static_cast<int >(SerialType::Normal)).toInt());
    if (serialType == SerialType::TcpServer) {
        tcpServerRadioButton->setChecked(true);
    } else if (serialType == SerialType::TcpClient) {
        tcpClientRadioButton->setChecked(true);
    } else if (serialType == SerialType::Bridge) {
        bridgeRadioButton->setChecked(true);
    } else if (serialType == SerialType::SerialBridge) {
        serialBridgeRadioButton->setChecked(true);
    } else {
        serialRadioButton->setChecked(true);
    }

    _serialType = serialType;

    settings.beginGroup("SerialSettings");
    auto nameIndex = settings.value("name", 0).toInt();
    auto baudRateIndex = settings.value("baud_rate", 5).toInt();
    auto dataBitsIndex = (QSerialPort::DataBits) settings.value("data_bits", 3).toInt();
    auto stopBitsIndex = (QSerialPort::StopBits) settings.value("stop_bits", 0).toInt();
    auto parityIndex = (QSerialPort::Parity) settings.value("parity", 0).toInt();
    auto sendText = settings.value("send_text", "").toString();

    auto maxCount = serialPortNameComboBox->maxCount();
    if (nameIndex > maxCount - 1) {
        nameIndex = 0;
    }
    serialPortNameComboBox->setCurrentIndex(nameIndex);
    serialPortBaudRateComboBox->setCurrentIndex(baudRateIndex);
    serialPortDataBitsComboBox->setCurrentIndex(dataBitsIndex);
    serialPortStopBitsComboBox->setCurrentIndex(stopBitsIndex);
    serialPortParityComboBox->setCurrentIndex(parityIndex);

    auto name2Index = settings.value("name2", 0).toInt();
    auto baudRate2Index = settings.value("baud_rate2", 5).toInt();
    auto dataBits2Index = (QSerialPort::DataBits) settings.value("data_bits2", 3).toInt();
    auto stopBits2Index = (QSerialPort::StopBits) settings.value("stop_bits2", 0).toInt();
    auto parity2Index = (QSerialPort::Parity) settings.value("parity2", 0).toInt();

    auto maxCount2 = serialPortNameComboBox->maxCount();
    if (name2Index > maxCount2 - 1) {
        name2Index = 0;
    }
    secondSerialPortNameComboBox->setCurrentIndex(name2Index);
    secondSerialPortBaudRateComboBox->setCurrentIndex(baudRate2Index);
    secondSerialPortDataBitsComboBox->setCurrentIndex(dataBits2Index);
    secondSerialPortStopBitsComboBox->setCurrentIndex(stopBits2Index);
    secondSerialPortParityComboBox->setCurrentIndex(parity2Index);

    settings.beginGroup("SerialReceiveSettings");
    auto addLineReturn = settings.value("add_line_return", true).toBool();
    auto displayReceiveDataAsHex = settings.value("display_receive_data_as_hex", false).toBool();
    auto addTimestamp = settings.value("add_timestamp", false).toBool();

    addLineReturnCheckBox->setChecked(addLineReturn);
    displayReceiveDataAsHexCheckBox->setChecked(displayReceiveDataAsHex);
    addReceiveTimestampCheckBox->setChecked(addTimestamp);

    settings.beginGroup("SerialSendSettings");
    auto sendAsHex = settings.value("send_as_hex", false).toBool();
    auto displaySendData = settings.value("display_send_data", false).toBool();
    auto displaySendDataAsHex = settings.value("display_send_data_as_hex", false).toBool();
    auto autoSend = settings.value("auto_send", false).toBool();
    auto autoSendInterval = settings.value("auto_send_interval", 100).toInt();
    auto emptyLineDelay = settings.value("empty_line_delay", 0).toInt();

    auto loopSend = settings.value("loop_send", false).toBool();

    hexCheckBox->setChecked(sendAsHex);
    displaySendDataCheckBox->setChecked(displaySendData);
    displaySendDataAsHexCheckBox->setChecked(displaySendDataAsHex);
    autoSendCheckBox->setChecked(autoSend);
    loopSendCheckBox->setChecked(loopSend);
    sendIntervalLineEdit->setText(QString::number(autoSendInterval));
    emptyLineDelayLindEdit->setText(QString::number(emptyLineDelay));

    auto sendLineReturn = settings.value("send_line_return", false).toBool();
    sendLineReturnCheckBox->setChecked(sendLineReturn);

    auto sendLineReturnType = LineReturn(
            settings.value("send_line_return_type", static_cast<int >(LineReturn::RN)).toInt());
    if (sendLineReturnType == LineReturn::R) {
        sendRReturnLineButton->setChecked(true);
    } else if (sendLineReturnType == LineReturn::N) {
        sendNReturnLineButton->setChecked(true);
    } else {
        sendRNLineReturnButton->setChecked(true);
    }

    settings.beginGroup("TcpSettings");
    auto ipList = getNetworkInterfaces();
    auto ipAddress = settings.value("tcp_address", "").toString();
    QString selectAddress = "";
    if (!ipAddress.isEmpty() && !ipList.isEmpty()) {
        auto found = false;
        for (const auto &ip:ipList) {
            if (getIpAddress(ip) == ipAddress) {
                selectAddress = ipAddress;
                found = true;
                break;
            }
        }
        if (!found) {
            selectAddress = getIpAddress(ipList.first());
        }
    }
    if (selectAddress.isEmpty()) {
        if (!ipList.isEmpty()) {
            do {
                for (const auto &ip:ipList) {
                    if (ip.type() == QNetworkInterface::Wifi && !getIpAddress(ip).isEmpty()) {
                        selectAddress = getIpAddress(ip);
                        break;
                    }
                }
                if (!selectAddress.isEmpty()) {
                    break;
                }
                for (const auto &ip:ipList) {
                    if (ip.type() == QNetworkInterface::Ethernet && !getIpAddress(ip).isEmpty()) {
                        selectAddress = getIpAddress(ip);
                    }
                }
                if (!selectAddress.isEmpty()) {
                    break;
                }

                selectAddress = getIpAddress(ipList.first());
            } while (false);
        }
    }

    tcpAddressLineEdit->setText(selectAddress);

    auto tcpPort = settings.value("tcp_port").toInt();
    tcpPortLineEdit->setText(QString::number(tcpPort));

    sendTextEdit->setText(sendText);

    settings.beginGroup("RunConfig");
    auto lastDir = settings.value("last_dir", "").toString();
    auto lastFilePath = settings.value("last_file_path", "").toString();

    runConfig = new RunConfig;
    runConfig->lastDir = lastDir;
    runConfig->lastFilePath = lastFilePath;

    _loopSend = loopSend;

    serialController = new LineSerialController();

    updateSendType();
}

3. 运行结果

Qt+C++串口调试接收发送数据曲线图,C++,qt,c++,开发语言,vs,visual studio,仿真,上位机

动画演示

Qt+C++串口调试接收发送数据曲线图,C++,qt,c++,开发语言,vs,visual studio,仿真,上位机 

三、在线协助:

如需安装运行环境或远程调试,见文章底部个人 QQ 名片,由专业技术人员远程协助!
1)远程安装运行环境,代码调试
2)Qt, C++, Python入门指导
3)界面美化
4)软件制作

当前文章连接:Python+Qt桌面端与网页端人工客服沟通工具_alicema1111的博客-CSDN博客

博主推荐文章:python人脸识别统计人数qt窗体-CSDN博客

博主推荐文章:Python Yolov5火焰烟雾识别源码分享-CSDN博客

                         Python OpenCV识别行人入口进出人数统计_python识别人数-CSDN博客

个人博客主页:alicema1111的博客_CSDN博客-Python,C++,网页领域博主

博主所有文章点这里alicema1111的博客_CSDN博客-Python,C++,网页领域博主文章来源地址https://www.toymoban.com/news/detail-668135.html

到了这里,关于Qt+C++串口调试接收发送数据曲线图的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Qt Charts - 绘制简单曲线图(1)

    QSplineSeries 类是Qt图表模块中的一个曲线系列类,用于绘制平滑的二次和三次曲线。这个系列通过在给定的数据点之间插值来绘制曲线,从而使得曲线更加平滑。 使用QSplineSeries时,需要将数据点作为QPointF类型的列表传递给数据集。然后将数据集添加到QChart中。可以使用QSpli

    2024年02月04日
    浏览(58)
  • 《Qt开发》基于QWT的曲线图绘制

    Qwt绘制曲线图 该示例包含以下功能: 1.使用qwt绘制曲线图 2.通过鼠标实现绘图的缩放,只缩放x轴或只缩放y轴或同时缩放 3.设置绘图区域和绘图区域外的背景颜色 4.通过点击图例实现曲线的显示和隐藏 QwtPlot绘图部件 头文件 #include qwt_plot.h 枚举类型 enum Axis { yLeft , yRight , xBott

    2023年04月08日
    浏览(60)
  • 【MATLAB】动态绘制曲线图(二维曲线)

    先看效果 ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨ 主程序: 加载数据的部分我省略了,就是data1这个矩阵 动态绘图函数: 这里暂时只支持设置线性、颜色、markerstyle这三个参数吧,主要是用 line() 这个函数把点连起来,设置line的参数就是曲线的样式,查看帮助文档 doc line 可以自定

    2024年02月16日
    浏览(42)
  • PyLab绘制曲线图

    PyLab 是一个面向 Matplotlib 的绘图库接口,其语法和 MATLAB 十分相近。它和 Pyplot 模快都够实现 Matplotlib 的绘图功能。PyLab 是一个单独的模块,随 Matplotlib 软件包一起安装,该模块的导包方式和 Pyplot 不同,如下所示: PyLab 是一个很便捷的模块,下面对它的使用方法做相应的介绍

    2024年02月16日
    浏览(58)
  • 【QCustomPlot】绘制 x-y 曲线图

    使用 QCustomPlot 绘图库辅助开发时整理的学习笔记。同系列文章目录可见 《绘图库 QCustomPlot 学习笔记》目录。本篇介绍如何使用 QCustomPlot 绘制 x-y 曲线图,需要 x 轴数据与 y 轴数据都已知,示例中使用的 QCustomPlot 版本为 Version 2.1.1 ,QT 版本为 5.9.2 。 目录 说明 1. 示例工程配

    2024年02月09日
    浏览(50)
  • 【KV260】利用XADC生成芯片温度曲线图

    如何在没有温度计的情况下,监控芯片的温度呢? Xilinx不仅提供了内置的XADC来观察温度,而且还可以生成如下的曲线图 具体操作如下 这时可以看到当前温度,最小温度,最大温度 上面是直接读取温度值。如果我们要长时间观察温度变化情况怎么办呢? 如下图 在黑色曲线区

    2024年02月15日
    浏览(41)
  • echarts折线图流动特效的实现(非平滑曲线)

    echarts官网:series-lines 注意:流动特效只支持非平滑曲线(smooth:false) series-lines路径图 : 用于带有起点和终点信息的线数据的绘制,主要用于地图上的航线,路线的可视化。 ECharts 2.x 里会用地图上的 markLine 去绘制迁徙效果,在 ECharts 3 里建议使用单独的 lines 类型图表。

    2024年02月14日
    浏览(45)
  • QT三驾马车(一)——实现上位机(串口数据发送和接收)

    以后同学们做项目一定会用到QT的三驾马车,QT的三驾马车即QT的串口编程,QT的网络编程和QT的GPIO,今天我们通过一个项目来介绍第一部分,QT的串口编程。 之前看过很多相关的文章,但是按照顺序来编译总是会出错,可是我自己还找不到原因,对于我这种新手小白来说极其

    2024年02月15日
    浏览(46)
  • YOLOv5|YOLOv7|YOLOv8改进之实验结果(四):将多种算法的Loss精度曲线图绘制到一张图上,便于YOLOv5、v7系列模型对比实验获取更多精度数据,丰富实验数据

    💡该教程为改进YOLO高阶指南,属于 《芒果书》 📚系列,包含大量的原创首发改进方式🚀 💡更多改进内容📚可以点击查看:YOLOv5改进、YOLOv7改进、YOLOv8改进、YOLOX改进原创目录 | 老师联袂推荐🏆 💡 🚀🚀🚀本博客内含·改进源代码·,按步骤操作运行改进后的代码即可

    2023年04月17日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包