QT应用开发学习(QT项目实战(仿写串口助手))

本文介绍了如何使用QT框架仿写一个串口助手,包括UI布局设计,如Label、Button等控件的使用,以及信号和槽的连接。作者强调了QT的信号槽机制,展示了如何自定义槽函数以及如何通过connect自动实现槽函数。代码部分展示了QTSerial.pro、qtserial.h和qtserial.cpp的关键代码,涉及串口的打开、关闭以及数据的读取和发送。
摘要由CSDN通过智能技术生成

本文主要是记录自己是如何仿写串口助手并实现效果的(本文并没有串口测试,但是其他按键功能已经编写成功)



前言

我也是在b站学习的QT,之前学习了C++的基础知识,那么在QT中就能够很好的运用出来了,并且本人之前有学习过安卓,对GUI开发比较熟练,所以如果觉得自己基础不好的可以先看看C++的知识。本文直接粘贴全部代码并逐步讲解。


一、显示效果

在这里插入图片描述
ui是自己实现的,可以去查找一些类似的串口助手编写,其中运动模式、下载模式,隐藏面板,隐藏历史都还未编写逻辑,主要功能已经实现。

二、讲解代码

都说万事开头难,我们要写一个串口助手,我们就需要先写一个串口助手的界面,我们在把里面的逻辑实现即可。

1.UI布局

我们先讲一下所需要的控件:双击ui文件打开(拖动左边的控件到中间的编辑框):
在这里插入图片描述

Label标签:用来标志控件,主要是用来告诉用户这个是用来做什么的,通常用来写文字。
Horizontal Spacer:横向弹簧,用来保持两个控件的控距,可以在右下角修改弹簧大小来实现控件距离的控制。
Vertical Spacer:纵向弹簧,效果和横向弹簧一样,只是作用对象时方向是上下
PushButton:按钮,用来点击来触发其他事件
CheckBox:勾选框,用来判断用户是否点击,作用和按钮差不多,但是这个可直接看到结果
GroupBox:框柱大的集合,主要也是用来调整距离
ComboBox:下拉框,可设置不同的值供选择
LineEdit:行编辑,提供给用户来编辑一行数据
TextEdit:文本便捷,效果差不多和行编辑一样
PlainTextEdit:追加编辑,通常用于接收数据显示

在拖动完控件后,我们需要修改不同的控件名字,用来在代码中查找到,修改名字只需要单击一下要修改的控件,在右上角会有显示,按需修改即可(一般使用驼峰命名)。

主要用到就这些控件,接下需要学会的是灵活布局:
在这里插入图片描述
横向布局就是让控件按行排列,纵向布局就是让控件纵向排列,栅格布局就是让控件一个接一个排列,像教室里的上课座位一样。

一般每几个控件就能实现横向布局或纵向布局,全部固定好后在实现栅格布局

2.信号和槽

我们通常使用的控件具有不同的信号,我们可以在帮助文档中查找到,如QPushButton:
在这里插入图片描述
在这里插入图片描述
**我们可以看到哪些信号会触发槽函数,QT中特有的信号和槽机制,可以让控件在接收到相对应的信号是触发对应的槽函数。**当然我们也可以自己编写槽函数,自定义编写槽函数需要满足一下几个条件。

自定义编写槽函数

1.在你的类中声明自定义槽函数。槽函数是普通的成员函数,但在声明时需要使用slots关键字进行修饰。例如

class MyCustomClass : public QObject
{
    Q_OBJECT

public slots:
    void myCustomSlot();
};

2.在类的实现文件(.cpp)中定义槽函数。你可以像编写普通成员函数一样来实现自定义的槽函数。例如:

void MyCustomClass::myCustomSlot()
{
    // 这里编写槽函数的具体实现逻辑
    // ...
}

3.将槽函数和信号连接起来。槽函数可以通过调用Qt的信号与槽机制来响应特定的信号。一般情况下,你可以在构造函数或其他适当的地方,使用connect函数来建立槽函数和信号的连接。例如:

MyCustomClass::MyCustomClass()
{
    // 假设有一个QPushButton的点击信号连接到myCustomSlot()槽函数
    QPushButton* button = new QPushButton("Click me");
    connect(button, &QPushButton::clicked, this, &MyCustomClass::myCustomSlot);
}

connect

connect函数是Qt中用于建立信号与槽连接的函数。它允许你将一个信号连接到一个槽函数,以便在信号发出时执行槽函数的代码。

在Qt中,信号是一种特殊的成员函数,用于通知其他对象某个事件的发生。当满足特定条件时,一个对象可以发出一个信号。槽函数是普通的成员函数,用于响应信号的发出并进行相应的处理。

connect函数用于连接信号和槽函数,建立二者之间的关联。它的基本语法如下:

connect(sender, &SenderClass::signal, receiver, &ReceiverClass::slot);

其中,sender是发出信号的对象的指针(或者是静态成员函数所属的类),signal是发出的信号,receiver是接收信号的对象的指针,slot是接收信号时要执行的槽函数。

需要注意的是,信号和槽函数的参数类型必须匹配,或者是可以进行隐式转换的类型。此外,要确保信号和槽函数的声明都在QObject的子类中,并在类的声明中使用Q_OBJECT宏。

connect函数可以连接不同对象之间的信号和槽函数,可以连接同一个对象的不同信号和槽函数,也可以连接不同信号和不同槽函数。一个信号可以连接多个槽函数,多个信号也可以连接到同一个槽函数。

通过使用connect函数,你可以将对象间的通信通过信号和槽机制来实现。这种机制使得对象之间的耦合度降低,并提供了一种方便灵活的方式来处理事件。

自动实现槽函数

通常我们使用控件时,QT已经帮我们写好了槽函数,我们无需再自己编写connet,只需要在UI中右击控件,点击转到槽,然后确定自己选择的信号即可。这样我们就可以在槽函数中编写其中的逻辑了。

代码讲解:

QTSerial.pro

需要注意的是使用QT中的Serial函数需要在QT += core gui 加入serialport,这个可以在帮助文档中查看到
在这里插入图片描述

#-------------------------------------------------
#
# Project created by QtCreator 2023-07-16T13:41:42
#
#-------------------------------------------------

QT       += core gui serialport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = QTSerial
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \
        main.cpp \
        qtserial.cpp

HEADERS += \
        qtserial.h

FORMS += \
        qtserial.ui

qtserial.h

#ifndef QTSERIAL_H
#define QTSERIAL_H

#include <QMainWindow>
#include <QSerialPort>
#include <QMessageBox>
#include <QComboBox>
#include <QCheckBox>
namespace Ui {
class QTSerial;
}

class QTSerial : public QMainWindow
{
    Q_OBJECT

public:
    explicit QTSerial(QWidget *parent = 0);
    ~QTSerial();

private slots://槽函数必须在这声明
    void on_OpenSerialBt_clicked();//打开串口按钮的槽函数声明
    void readyRead_slots();//准备读取的槽函数声明
    void on_sendBt_clicked();//发送按钮的槽函数声明
    void on_cleanSendEdit_clicked();//清空发送区的槽函数声明
    void on_CleanRec_clicked();//清空接收区的槽函数声明
    void on_HexPrint_stateChanged(int arg1);//进制转换的槽函数声明

private:
    Ui::QTSerial *ui;
    QSerialPort *serialport;//定义一个QSerialPort的指针变量,需要包含头文件<QSerialPort>,在QT中,包含类的头文件是无.h后缀的

};

#endif // QTSERIAL_H

qtserial.cpp

#include "qtserial.h"
#include "ui_qtserial.h"
#include <QDebug>
#include <QSerialPortInfo>
QTSerial::QTSerial(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::QTSerial)
{
    ui->setupUi(this);
    serialport = new QSerialPort(this);//new一个对象出来
    QStringList serialNamePort;//存储串口名称
    connect(serialport, SIGNAL(readyRead()), this, SLOT(readyRead_slots()));//当有数据进来的时候会触发这个槽函数

    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())//自动搜索串口信息
    {
        serialNamePort << info.portName();//将搜索到的串口信息给定义的类
    }

    ui->SerialBox->addItems(serialNamePort);
}

QTSerial::~QTSerial()
{
    delete serialport;
    delete ui;
}

void QTSerial::on_OpenSerialBt_clicked()
{
   if(serialport->open(QIODevice::ReadWrite) == true)
   {
       QMessageBox::information(this, "提示", "打开成功");
   }
   else
   {
       QMessageBox::information(this, "提示", "打开失败");
   }
    QString setBaudRate = ui->BoundBox->currentText();
    QString setDateBits = ui->DataBitBox->currentText();
    QString setParity = ui->ParityBox->currentText();
    serialport->setPortName(ui->SerialBox->currentText());//设置端口号
    switch (setBaudRate.toInt()) {
        case 4800:
            serialport->setBaudRate(4800);
            break;
        case 9600:
            serialport->setBaudRate(9600);
        case 115200:
            serialport->setBaudRate(115200);
            break;
        default:
            break;
    }
    switch (setDateBits.toInt()) {
        case 7:
            serialport->setDataBits(QSerialPort::Data7);
            break;
        case 8:
            serialport->setBaudRate(QSerialPort::Data8);
        default:
            break;
    }
    if(ui->StopBitBox->currentText() == "1"){
        serialport->setStopBits(QSerialPort::OneStop);
    }else if(ui->StopBitBox->currentText() == "1.5"){
            serialport->setStopBits(QSerialPort::OneAndHalfStop);
    }else if(ui->StopBitBox->currentText() == "2"){
            serialport->setStopBits(QSerialPort::TwoStop);
    }
    if(setParity == "None")
    {
        serialport->setParity(QSerialPort::NoParity);
    }

}
void QTSerial::readyRead_slots()//接收数据
{
    QString buf;
    buf = QString(serialport->readAll());
    ui->receTextEdit->appendPlainText(buf);
}
void QTSerial::on_sendBt_clicked()
{
    serialport->write(ui->sendlineEdit->text().toUtf8().data());
}

void QTSerial::on_cleanSendEdit_clicked()
{
    ui->sendlineEdit->clear();
}

void QTSerial::on_CleanRec_clicked()
{
    ui->receTextEdit->clear();
}

void QTSerial::on_HexPrint_stateChanged(int arg1)
{
    int sendLineEdit,decimalNumber1;
    QString decimalNumber;
    bool ok;
    QString hexString;
    switch (arg1) {
    case 0:
        decimalNumber = ui->sendlineEdit->text();
        decimalNumber1 = decimalNumber.toInt(&ok, 16);

        if (ok) {
            ui->sendlineEdit->setText(QString::number(decimalNumber1));
        } else {
            QMessageBox::warning(nullptr, "错误", "转换失败!");
        }
        break;
    case 2:
        sendLineEdit = ui->sendlineEdit->text().toInt();
        hexString = QString("%1").arg(sendLineEdit, 0, 16);
        ui->sendlineEdit->setText(hexString);
        break;
    default:
        break;
    }
}

总结

这就是仿写串口助手了,基本逻辑功能已经实现了,如果有什么错误请纠正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值