QT(c++)开发自学笔记:1.串口

新建工程与界面介绍

新建文件,不要选错成Application (Qt for python)了

这里选择QDialog

新建之后可以点开看到文件夹中的dialog.cpp

cpp 复制代码
#include "dialog.h"
#include "./ui_dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::Dialog)
{
    ui->setupUi(this);
}

Dialog::~Dialog()
{
    delete ui;
}
  • Dialog::Dialog(QWidget *parent):这是成员函数的定义,使用作用域解析运算符 :: 指定函数属于Dialog类。函数名与类名相同,表示构造函数 。参数列表(QWidget *parent) 定义了一个指针参数parent,类型为QWidget*(Qt的窗口部件基类指针),用于传递父窗口指针。
  • : QDialog(parent):这是初始化列表 (Initializer List)的开始,以冒号:开头,用于在函数体执行前初始化基类和成员变量。格式为: 成员/基类(参数)。调用基类QDialog的构造函数,传递parent参数。QDialog是Qt的对话框基类,这里实现继承初始化。
  • , ui(new Ui::Dialog):初始化列表的延续,以逗号,分隔多个初始化项。初始化成员变量ui(在头文件中声明为Ui::Dialog *ui;),使用new动态分配内存,创建Ui::Dialog对象的实例。Ui::Dialog是命名空间Ui下的类(Qt UI生成)。
  • { ui->setupUi(this); }:函数体,用花括号{}包围。内部语句ui->setupUi(this);
    • ui->:使用箭头运算符->访问指针ui指向的对象成员。
    • setupUi(this):调用Ui::Dialog类的成员函数setupUi,参数this是当前对象指针(Dialog*),用于将UI控件绑定到当前对话框。
  • Dialog::~Dialog():表示析构函数 (Destructor),销毁对话框 。无参数列表(),且无返回值类型。
  • { delete ui; }:函数体,用{}包围。内部语句delete ui;
    • delete 是C++运算符,用于释放动态分配的内存(对应构造函数中的new)。
    • ui 是指针变量,delete ui 会调用Ui::Dialog的析构函数并释放内存。

一些快捷键

ctrl+B:编译

ctrl+R:运行

F4:再.h和.cpp直接切换

添加控件的基本形式

新建之后,点开dialog.ui

新建一个ComBox

点击该框,右下角可以改名

注意左下角的控件

报错问题:当前QT版本不支持串口

运行完程序之后,会自动弹出QT支持包,选择一个版本功能中有"Serial Port"功能的进行安装(比如我6.9.2不支持串口,但是6.9.3可以),然后再到左侧框"项目"选项中把6.9.3相关的全部运行,6.9.2的给关掉

注意:只开前两个,后面两个不要开(我这样之后仍然报错,仍未解决) 所以采用以下方法:

直接打开Qt维护工具,也就是MaintenanceTool.exe

把6.9.2给全部取消勾选,点下一步

然后等移除之后,新建一个工程,刚才那个工程的东西全部复制过来算了

完整添加控件和代码

添加以下控件,并精确设置objectName(在属性编辑器中,右上角的Property Editor):

控件类型 objectName(名称) 布局建议位置
QComboBox comboBoxPort 上方,选择串口
QComboBox comboBoxBaud 上方,选择波特率
QPushButton pushButtonOpen 中间,打开/关闭按钮
QLineEdit lineEditSend 下方,发送输入框
QPushButton pushButtonSend 下方,发送按钮
QTextEdit textEditReceive 最下方,接收显示区(设置readOnly=true,便于只读)

最终布局类似于这样:

dialog.h文件代码如下:

cpp 复制代码
#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QSerialPort>
#include <QSerialPortInfo>

QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = nullptr);
    ~Dialog();

private slots:
    void openSerialPort();
    void closeSerialPort();
    void sendData();
    void readData();

private:
    Ui::Dialog *ui;
    QSerialPort *serial;
};

#endif // DIALOG_H

dialog.cpp代码如下:

cpp 复制代码
#include "dialog.h"
#include "./ui_dialog.h"
#include <QDebug>
#include <QMessageBox>

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::Dialog)
    , serial(new QSerialPort(this))
{
    ui->setupUi(this);

    // 假设UI元素:ui->comboBoxPort (QComboBox for ports), ui->comboBoxBaud (QComboBox for baud rates),
    // ui->pushButtonOpen (QPushButton for open/close), ui->textEditReceive (QTextEdit for received data),
    // ui->lineEditSend (QLineEdit for send data), ui->pushButtonSend (QPushButton for send).

    // 填充可用串口
    for (const QSerialPortInfo &info : QSerialPortInfo::availablePorts()) {
        ui->comboBoxPort->addItem(info.portName());
    }

    // 填充常见波特率
    ui->comboBoxBaud->addItems({"9600", "19200", "38400", "57600", "115200"});

    // 连接信号槽
    connect(ui->pushButtonOpen, &QPushButton::clicked, this, &Dialog::openSerialPort);
    connect(ui->pushButtonSend, &QPushButton::clicked, this, &Dialog::sendData);
    connect(serial, &QSerialPort::readyRead, this, &Dialog::readData);
    connect(serial, QOverload<QSerialPort::SerialPortError>::of(&QSerialPort::errorOccurred),
            this, [](QSerialPort::SerialPortError error) {
                if (error != QSerialPort::NoError) {
                    qDebug() << "Serial port error:" << error;
                }
            });

    serial->setBaudRate(QSerialPort::Baud9600); // 默认波特率
    serial->setDataBits(QSerialPort::Data8);
    serial->setParity(QSerialPort::NoParity);
    serial->setStopBits(QSerialPort::OneStop);
    serial->setFlowControl(QSerialPort::NoFlowControl);
}

Dialog::~Dialog()
{
    if (serial->isOpen()) {
        serial->close();
    }
    delete ui;
}

void Dialog::openSerialPort()
{
    if (serial->isOpen()) {
        closeSerialPort();
    } else {
        serial->setPortName(ui->comboBoxPort->currentText());
        serial->setBaudRate(ui->comboBoxBaud->currentText().toInt());
        if (serial->open(QIODevice::ReadWrite)) {
            ui->pushButtonOpen->setText("关闭串口");
            QMessageBox::information(this, "成功", "串口打开成功");
        } else {
            QMessageBox::warning(this, "错误", "无法打开串口: " + serial->errorString());
        }
    }
}

void Dialog::closeSerialPort()
{
    if (serial->isOpen()) {
        serial->close();
        ui->pushButtonOpen->setText("打开串口");
        QMessageBox::information(this, "成功", "串口关闭成功");
    }
}

void Dialog::sendData()
{
    if (serial->isOpen() && !ui->lineEditSend->text().isEmpty()) {
        QByteArray data = ui->lineEditSend->text().toUtf8();
        serial->write(data);
        ui->lineEditSend->clear();
    } else {
        QMessageBox::warning(this, "错误", "串口未打开或发送数据为空");
    }
}

void Dialog::readData()
{
    if (serial->bytesAvailable()) {
        QByteArray data = serial->readAll();
        ui->textEditReceive->append(data);
    }
}

main.cpp代码如下:

cpp 复制代码
#include "dialog.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();
    return a.exec();
}

CMakeLists.txt代码如下:

cpp 复制代码
cmake_minimum_required(VERSION 3.16)

project(Text1004Test VERSION 0.1 LANGUAGES CXX)

# 手动指定Qt 6.9.3完整路径(用正斜杠,无空格;替换为您的确切路径,例如 D:/QTWorks/6.9.3/mingw_64)
set(CMAKE_PREFIX_PATH "D:/QTWorks/6.9.3/mingw_64")

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 临时调试:启用详细查找日志(构建后移除)
# set(CMAKE_FIND_DEBUG_MODE TRUE)

# 查找Qt 6(优先),包含Widgets和SerialPort组件
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets SerialPort)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets SerialPort)

# 调试输出:打印找到的Qt路径和组件状态
message(STATUS "Qt Version: ${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}")
message(STATUS "Qt Install Prefix: ${Qt6_DIR}/..")
message(STATUS "SerialPort Found: ${Qt6SerialPort_FOUND}")  # 应为TRUE

set(PROJECT_SOURCES
        main.cpp
        dialog.cpp
        dialog.h
        dialog.ui  # 确保包含.ui文件
)

if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
    qt_add_executable(Text1004Test
        MANUAL_FINALIZATION
        ${PROJECT_SOURCES}
    )
else()
    if(ANDROID)
        add_library(Text1004Test SHARED
            ${PROJECT_SOURCES}
        )
    else()
        add_executable(Text1004Test
            ${PROJECT_SOURCES}
        )
    endif()
endif()

# 链接Widgets和SerialPort
target_link_libraries(Text1004Test PRIVATE
    Qt${QT_VERSION_MAJOR}::Widgets
    Qt${QT_VERSION_MAJOR}::SerialPort
)

# iOS/macOS捆绑设置
if(${QT_VERSION} VERSION_LESS 6.1.0)
  set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.Text1004Test)
endif()
set_target_properties(Text1004Test PROPERTIES
    ${BUNDLE_ID_OPTION}
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
    MACOSX_BUNDLE TRUE
    WIN32_EXECUTABLE TRUE
)

include(GNUInstallDirs)
install(TARGETS Text1004Test
    BUNDLE DESTINATION .
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

if(QT_VERSION_MAJOR EQUAL 6)
    qt_finalize_executable(Text1004Test)
endif()

然后再下个串口调试助手,开一对虚拟串口,两个互选一下试试互发消息

能互相收到就成功了,这个简单的例子可以用来熟悉一下这种"控件+代码"的设计模式

相关推荐
范特西_3 小时前
两个无重叠子数组的最大和
c++·算法
dot to one3 小时前
应用层:Http、Https
linux·c++·网络协议
岑梓铭3 小时前
计算机网络第四章(10)——网络层《路由算法+路由协议》
网络·笔记·计算机网络·考研·智能路由器·408
YongCheng_Liang3 小时前
网络工程师笔记10-BGP协议
运维·网络·笔记
JJJJ_iii4 小时前
【深度学习04】PyTorch:损失函数、优化器、模型微调、保存与加载
人工智能·pytorch·笔记·python·深度学习·机器学习
lingggggaaaa4 小时前
小迪安全v2023学习笔记(九十七天)—— 云原生篇&Kubernetes&K8s安全&API&Kubelet未授权访问&容器执行
java·笔记·学习·安全·网络安全·云原生·kubernetes
十安_数学好题速析4 小时前
系数调整:四项平方和的最小值攻略
笔记·学习·高考
2401_841495645 小时前
【数据结构】链栈的基本操作
java·数据结构·c++·python·算法·链表·链栈
huangyuchi.5 小时前
【Linux实战 】Linux 线程池的设计、实现与单例模式应用
linux·c++·单例模式·线程池·懒汉模式·项目·linux系统