QT串口助手(二):参数配置

做者:zzssdd2c++

E-mail:zzssdd2@foxmail.com框架

1、前言

开发环境:Qt5.12.10 + MinGW函数

主要实现功能字体

  • 串口参数的配置:波特率数据位中止位校验位
  • 本机串口设备的查询与添加显示
  • 串口设备的手动更新与打开关闭

涉及的知识点ui

  • 串口类QSerialPortQSerialPortInfo的使用
  • 自定义波特率的实现
  • QComboBox下拉列表自适应文本长度显示
  • 控件QPushButtonQComboBox的使用

2、功能实现

下面开始逐步讲解以上列举的功能this

2.一、串口设备的查询添加

建立一个串口设备信息列表和串口设备号列表,遍历本机可用串口而后添加到列表中,将设备信息列表显示在对应的QComboBox控件中,设备号列表用来后面打开串口设备使用。code

/* 遍历可用串口设备 */
QStringList SerialPort_Name;
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
    SerialPort_Name << info.portName()+':'+info.description();
    serialDevice << info.portName();
}
/* 添加到串口设备显示框 */
ui->SerialNum_Box->addItems(SerialPort_Name);

2.二、下拉列表自适应

此时已经将串口设备信息添加到下拉框中了,可是下拉框此时是固定长度,若是串口设备信息比较长则没法显示彻底(以省略号展现),那么就须要实现下拉框根据设备信息字符串长度适配功能。原理就是遍历列表中全部设备信息字符串的长度,找出最大值而后将下拉框长度设置到能彻底显示最大长度字符串。对象

/* 获取最长字符串 */
int maxlen = 0;
for (int index = 0; index < ui->SerialNum_Box->count(); index++)
{
    if (ui->SerialNum_Box->itemText(index).length() > maxlen)
    {
        maxlen = ui->SerialNum_Box->itemText(index).length();
    }
}
/*获取字体磅值转换为像素值*/
int fontsize = ui->SerialNum_Box->font().pointSize();//获取字体的磅值
ui->SerialNum_Box->view()->setFixedWidth(fontsize * maxlen * 0.75);//设置像素值

这里涉及字体磅与像素对应关系,由于setFixedWidth函数参数单位是像素。下面列出字号不一样单位对照表:blog

中文字号 英文字号(磅) 毫米 像素
1英寸 72pt 25.30mm 95.6px
大特号 63pt 22.14mm 83.7px
特号 54pt 18.97mm 71.7px
初号 42pt 14.82mm 56px
小初 36pt 12.70mm 48px
一号 26pt 9.17mm 34.7px
小一 24pt 8.47mm 32px
二号 22pt 7.76mm 29.3px
小二 18pt 6.35mm 24px
三号 16pt 5.64mm 21.3px
小三 15pt 5.29mm 20px
四号 14pt 4.94mm 18.7px
小四 12pt 4.23mm 16px
五号 10.5pt 3.70mm 14px
小五 9pt 3.18mm 12px
六号 7.5pt 2.56mm 10px
小六 6.5pt 2.29mm 8.7px
七号 5.5pt 1.94mm 7.3px
八号 5pt 1.76mm 6.7px

由上表可知:1inch = 72pt,那么1pt = 1 / 72(inch),咱们使用的9pt字号就是9 * (1 / 72) = 1 / 8(inch).继承

DPI(dots per inch)表示每英寸可以打印的格点数量(能够理解为像素点数),这个值通常默认值为96。在小字体模式下分辨率是96DPI(大字体模式下分辨率是120DPI),也就是说每英寸能显示96个像素,由此能够算出咱们使用的9pt字号对应像素:96dpi / (1 / 8)inch = 12px,那么1px = 9pt / 12px = 0.75pt。

添加该功能后先后对比:

2.三、串口参数的配置

这部分功能实现串口参数的配置,主要有波特率、数据位、中止位、校验位等,根据下拉框选择的参数进行配置。

/* 设置波特率 */
switch (ui->Bandrate_Box->currentIndex())
{
    case 0:
        serial->setBaudRate(QSerialPort::Baud1200,QSerialPort::AllDirections);
        break;
    case 1:
        serial->setBaudRate(QSerialPort::Baud2400,QSerialPort::AllDirections);
        break;
    case 2:
        serial->setBaudRate(QSerialPort::Baud4800,QSerialPort::AllDirections);
        break;
    case 3:
        serial->setBaudRate(QSerialPort::Baud9600,QSerialPort::AllDirections);
        break;
    case 4:
        serial->setBaudRate(QSerialPort::Baud19200,QSerialPort::AllDirections);
        break;
    case 5:
        serial->setBaudRate(QSerialPort::Baud38400,QSerialPort::AllDirections);
        break;
    case 6:
        serial->setBaudRate(QSerialPort::Baud57600,QSerialPort::AllDirections);
        break;
    case 7:
        serial->setBaudRate(QSerialPort::Baud115200,QSerialPort::AllDirections);
        break;
    case 8:
        /*自定义波特率*/
    default:
        break;
}
/* 设置数据位 */
switch (ui->Databit_Box->currentIndex()) {
    case 0:
        serial->setDataBits(QSerialPort::Data5);
        break;
    case 1:
        serial->setDataBits(QSerialPort::Data6);
        break;
    case 2:
        serial->setDataBits(QSerialPort::Data7);
        break;
    case 3:
        serial->setDataBits(QSerialPort::Data8);
        break;
    default:
        break;
}
/* 设置中止位 */
switch (ui->Stopbit_Box->currentIndex()) {
    case 0:
        serial->setStopBits(QSerialPort::OneStop);
        break;
    case 1:
        serial->setStopBits(QSerialPort::OneAndHalfStop);
        break;
    case 2:
        serial->setStopBits(QSerialPort::TwoStop);
        break;
    default:
        break;
}
/* 设置校验位 */
switch (ui->Parity_Box->currentIndex()) {
    case 0:
        serial->setParity(QSerialPort::NoParity);
        break;
    case 1:
        serial->setParity(QSerialPort::EvenParity);
        break;
    case 2:
        serial->setParity(QSerialPort::OddParity);
        break;
    default:
        break;
}
/* 设置流控制 */
serial->setFlowControl(QSerialPort::NoFlowControl);

2.四、自定义波特率

在QT的源码文件qserialport.h中枚举了经常使用的波特率:

enum BaudRate {
        Baud1200 = 1200,
        Baud2400 = 2400,
        Baud4800 = 4800,
        Baud9600 = 9600,
        Baud19200 = 19200,
        Baud38400 = 38400,
        Baud57600 = 57600,
        Baud115200 = 115200,
        UnknownBaud = -1
    };

可是若是没有列出咱们用到的波特率,那么就须要实现自定义波特率(好比我之前参与的一个项目就要求串口使用500000bps波特率)。实现方式就是将波特率QComboBox列表最后一项设置为自定义波特率,当使用自定义波特率时则获取填写的自定义值并转换为qint32类型数值,而后将该参数设置为波特率,以下:

qint32 CustomBandrate = ui->Bandrate_Box->currentText().toUInt();
serial->setBaudRate(CustomBandrate, QSerialPort::AllDirections);

这里须要注意的是波特率列表自定义项以前的都是对应的固定波特率值,若是不是选择自定义波特率应当设置为不可编辑状态,只有选择自定义波特率时才能够编辑。这里使用QComboBox的信号currentIndexChanged触发槽函数实现该功能:若是选择了自定义波特率,则将下拉框设为可编辑,不然设为不能编辑

/*下拉项改变信号槽:重载函数如有多种不一样参数类型则使用信号槽链接时有必要指定参数类型*/
connect(ui->Bandrate_Box, QOverload<int>::of(&QComboBox::currentIndexChanged),[=](int index){
    if (index == 8) {
        ui->Bandrate_Box->setEditable(true);
        ui->Bandrate_Box->setCurrentText(NULL);
    } else {
        ui->Bandrate_Box->setEditable(false);
    }
});

参数配置列表完成以下:

2.五、串口打开与关闭

串口开关按钮点击信号对应的槽函数实现内容以下:

/*
    函   数:on_SerialPortSwitch_Bt_clicked
    描   述:开关串口按键点击槽函数
    输   入:无
    输   出:无
*/
void Widget::on_SerialPortSwitch_Bt_clicked()
{
    if (ui->SerialPortSwitch_Bt->text() == "打开")
    {
        /* 建立串口对象 */
        serial = new QSerialPort(this);
        /* 建立接收数据信号槽 */
        connect(serial, &QSerialPort::readyRead, this, &Widget::SerialPortReadyRead_slot);
        /* 设置串口号 */
        QString dev = serialDevice.at(ui->SerialNum_Box->currentIndex());
        serial->setPortName(dev);
        /* 设置波特率 */
        /* 设置数据位 */
        /* 设置中止位 */
        /* 设置校验位 */
        /* 设置流控制 */
        /* 打开串口 */
        if (serial->open(QIODevice::ReadWrite) != true)
        {
            QMessageBox::critical(this, "提示", "打开失败");
            return;
        }
        /*标记串口已打开*/
        global_struct.isSerialOpen = true;
        /*设置文本*/
        ui->SerialPortSwitch_Bt->setText("关闭");
    }
    else
    {
        /*关闭并删除串口对象*/
        serial->close();
        serial->deleteLater();
        /*标记串口已关闭*/
        global_struct.isSerialOpen = false;
        /*设置文本*/
        ui->SerialPortSwitch_Bt->setText("打开");
    }
}

2.六、串口设备的刷新

串口设备刷新按钮点击信号对应的槽函数功能实现以下:

/*
    函   数:on_ComFlush_BT_clicked
    描   述:串口设备刷新按钮槽函数
    输   入:无
    输   出:无
*/
void Widget::on_ComFlush_BT_clicked()
{
    ui->SerialNum_Box->clear();
    FindSerialPort();
}

/*
    函   数:FindSerialPort
    描   述:查找串口并添加到QComboBox
    输   入:无
    输   出:无
*/
void Widget::FindSerialPort(void)
{
    /* 遍历可用串口并添加到显示框 */
    QStringList SerialPort_Name;
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        SerialPort_Name << info.portName()+':'+info.description();
        serialDevice << info.portName();
    }
    ui->SerialNum_Box->addItems(SerialPort_Name);
    /*设置下拉框列表宽度*/
    int maxlen = 0;
    for (int index = 0; index < ui->SerialNum_Box->count(); index++)
    {
        if (ui->SerialNum_Box->itemText(index).length() > maxlen)
        {
            maxlen = ui->SerialNum_Box->itemText(index).length();
        }
    }
    int fontsize = ui->SerialNum_Box->font().pointSize();
    ui->SerialNum_Box->view()->setFixedWidth(fontsize * maxlen * 0.75);
}

3、总结

本篇文章主要是讲如何对串口参数进行配置及QComboBox等控件的一些基本操做。除此以外,还应该了解必定C++知识,好比类的继承、函数重载、Lambda表达式等;还有就是应该掌握QT信号槽的使用,由于这是QT框架中很是重要的通讯机制,能够说使用QT开发必然离不开信号槽的应用。

相关文章
相关标签/搜索