QT串口调试助手

 1.概述

完成串口助手相应功能

 2.界面设计

在这里插入图片描述

 3.开发

  3.1 串口调试助手自动检测串口

在头文件中添加: #include <QSerialPortInfo>.pro中添加:   QT += serialport

在这里插入图片描述

    //[static] QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
    QList<QSerialPortInfo> serialList = QSerialPortInfo::availablePorts();  //获取可用的串口列表
    for(QSerialPortInfo serialinfo : serialList){   //迭代器迭代遍历
        qDebug() << serialinfo.portName();
        ui->comboBox_serialNum->addItem(serialinfo.portName()); //将可用的串口添加到串口中

  3.2 串口调试助手打开串口(配置串口参数)

在这里插入图片描述
在这里插入图片描述

在头文件中添加: #include <QSerialPortInfo>.pro中添加:   QT += serialport
/*
 * --首先实例化串口对象而后配置串口参数
    1.选择端口号
    2.配置波特率
    3.配置数据位
    4.配置校验位
    5.配置停止位
    6.流控
*/

/*
    enum Parity {
        NoParity = 0,
        EvenParity = 2,
        OddParity = 3,
        SpaceParity = 4,
        MarkParity = 5,
        UnknownParity = -1
    };
*/
void Widget::on_btnCloseOrOpen_clicked()
{
    if(!serialStatus){  //打开时
        //1.选择端口号
        serialPort->setPortName(ui->comboBox_serialNum->currentText());
        //2.配置波特率
        serialPort->setBaudRate(ui->comboBox_boautrate->currentText().toInt());
        //3.配置数据位
        serialPort->setDataBits(QSerialPort::DataBits(
                                    ui->comboBox_databit->currentText().toUInt()));
        //4.配置校验位
        switch (ui->comboBox_jiaoyan->currentIndex()) {
        case 0:
            serialPort->setParity(QSerialPort::NoParity);
            break;
        case 1:
            serialPort->setParity(QSerialPort::EvenParity);
            break;
        case 2:
            serialPort->setParity(QSerialPort::MarkParity);
            break;
        case 3:
            serialPort->setParity(QSerialPort::OddParity);
            break;
        case 4:
            serialPort->setParity(QSerialPort::SpaceParity);
            break;
        default:
            serialPort->setParity(QSerialPort::UnknownParity);
            break;

        }
        //5.配置停止位
        serialPort->setStopBits(QSerialPort::StopBits(
                                    ui->comboBox_stopbit->currentText().toUInt()));
        //6.配置流控
        if(ui->comboBox_fileCon->currentText() == "None"){
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
        }
        //7.打开串口
        if(serialPort->open(QIODevice::ReadWrite)){ //打开状态
            qDebug() << "serial open success";
            ui->comboBox_databit->setEnabled(false); //使其失效
            ui->comboBox_fileCon->setEnabled(false); //使其失效
            ui->comboBox_jiaoyan->setEnabled(false); //使其失效
            ui->comboBox_stopbit->setEnabled(false); //使其失效
            ui->comboBox_boautrate->setEnabled(false); //使其失效
            ui->comboBox_serialNum->setEnabled(false); //使其失效
            ui->btnCloseOrOpen->setText(QString("关闭串口"));
            ui->btnSendContext->setEnabled(true);
            serialStatus = true;
        }else{  //打开失败
            QMessageBox msgBox;
            msgBox.setWindowTitle("打开串口错误");
            msgBox.setText("打开失败,串口可能被占用.");
            msgBox.exec();
        }
    }else{  //关闭时
        serialPort->close();
        ui->btnCloseOrOpen->setText("打开串口");
        ui->comboBox_databit->setEnabled(true); //使其失效
        ui->comboBox_fileCon->setEnabled(true); //使其失效
        ui->comboBox_jiaoyan->setEnabled(true); //使其失效
        ui->comboBox_stopbit->setEnabled(true); //使其失效
        ui->comboBox_boautrate->setEnabled(true); //使其失效
        ui->comboBox_serialNum->setEnabled(true); //使其失效
        ui->btnSendContext->setEnabled(false);
        serialStatus = false;
    }
}

  3.3 对发送状态界面进行优化

	1.未打开时数据可设置,字符为打开串口
	2.打开后数据不可设置,字符变为关闭串口
	3.串口打开失败时有窗口提示

   3.3.1 Checkable

在这里插入图片描述

//checkable默认为false 点击一下为true 再点为false
void Widget::on_btnCloseOrOpen_clicked(bool checked)
{
    if(checked){  //打开时
        //1.选择端口号
        serialPort->setPortName(ui->comboBox_serialNum->currentText());
        //2.配置波特率
        serialPort->setBaudRate(ui->comboBox_boautrate->currentText().toInt());
        //3.配置数据位
        serialPort->setDataBits(QSerialPort::DataBits(
                                    ui->comboBox_databit->currentText().toUInt()));
        //4.配置校验位
        switch (ui->comboBox_jiaoyan->currentIndex()) {
        case 0:
            serialPort->setParity(QSerialPort::NoParity);
            break;
        case 1:
            serialPort->setParity(QSerialPort::EvenParity);
            break;
        case 2:
            serialPort->setParity(QSerialPort::MarkParity);
            break;
        case 3:
            serialPort->setParity(QSerialPort::OddParity);
            break;
        case 4:
            serialPort->setParity(QSerialPort::SpaceParity);
            break;
        default:
            serialPort->setParity(QSerialPort::UnknownParity);
            break;

        }
        //5.配置停止位
        serialPort->setStopBits(QSerialPort::StopBits(
                                    ui->comboBox_stopbit->currentText().toUInt()));
        //6.配置流控
        if(ui->comboBox_fileCon->currentText() == "None"){
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
        }
        //7.打开串口
        if(serialPort->open(QIODevice::ReadWrite)){ //打开状态
            qDebug() << "serial open success";
            ui->comboBox_databit->setEnabled(false); //使其失效
            ui->comboBox_fileCon->setEnabled(false); //使其失效
            ui->comboBox_jiaoyan->setEnabled(false); //使其失效
            ui->comboBox_stopbit->setEnabled(false); //使其失效
            ui->comboBox_boautrate->setEnabled(false); //使其失效
            ui->comboBox_serialNum->setEnabled(false); //使其失效
            ui->btnCloseOrOpen->setText(QString("关闭串口"));
            ui->btnSendContext->setEnabled(true);
           // serialStatus = true;
        }else{  //打开失败
            QMessageBox msgBox;
            msgBox.setWindowTitle("打开串口错误");
            msgBox.setText("打开失败,串口可能被占用.");
            msgBox.exec();
        }
    }else{  //关闭时
        serialPort->close();
        ui->btnCloseOrOpen->setText("打开串口");
        ui->comboBox_databit->setEnabled(true); //使其失效
        ui->comboBox_fileCon->setEnabled(true); //使其失效
        ui->comboBox_jiaoyan->setEnabled(true); //使其失效
        ui->comboBox_stopbit->setEnabled(true); //使其失效
        ui->comboBox_boautrate->setEnabled(true); //使其失效
        ui->comboBox_serialNum->setEnabled(true); //使其失效
        ui->btnSendContext->setEnabled(false);
       // serialStatus = false;
    }
}

   3.3.2 设置状态标志位

在这里插入图片描述

void Widget::on_btnCloseOrOpen_clicked()
{
    if(!serialStatus){  //打开时
        //1.选择端口号
        serialPort->setPortName(ui->comboBox_serialNum->currentText());
        //2.配置波特率
        serialPort->setBaudRate(ui->comboBox_boautrate->currentText().toInt());
        //3.配置数据位
        serialPort->setDataBits(QSerialPort::DataBits(
                                    ui->comboBox_databit->currentText().toUInt()));
        //4.配置校验位
        switch (ui->comboBox_jiaoyan->currentIndex()) {
        case 0:
            serialPort->setParity(QSerialPort::NoParity);
            break;
        case 1:
            serialPort->setParity(QSerialPort::EvenParity);
            break;
        case 2:
            serialPort->setParity(QSerialPort::MarkParity);
            break;
        case 3:
            serialPort->setParity(QSerialPort::OddParity);
            break;
        case 4:
            serialPort->setParity(QSerialPort::SpaceParity);
            break;
        default:
            serialPort->setParity(QSerialPort::UnknownParity);
            break;

        }
        //5.配置停止位
        serialPort->setStopBits(QSerialPort::StopBits(
                                    ui->comboBox_stopbit->currentText().toUInt()));
        //6.配置流控
        if(ui->comboBox_fileCon->currentText() == "None"){
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
        }
        //7.打开串口
        if(serialPort->open(QIODevice::ReadWrite)){ //打开状态
            qDebug() << "serial open success";
            ui->comboBox_databit->setEnabled(false); //使其失效
            ui->comboBox_fileCon->setEnabled(false); //使其失效
            ui->comboBox_jiaoyan->setEnabled(false); //使其失效
            ui->comboBox_stopbit->setEnabled(false); //使其失效
            ui->comboBox_boautrate->setEnabled(false); //使其失效
            ui->comboBox_serialNum->setEnabled(false); //使其失效
            ui->btnCloseOrOpen->setText(QString("关闭串口"));
            ui->btnSendContext->setEnabled(true);
            serialStatus = true;
        }else{  //打开失败
            QMessageBox msgBox;
            msgBox.setWindowTitle("打开串口错误");
            msgBox.setText("打开失败,串口可能被占用.");
            msgBox.exec();
        }
    }else{  //关闭时
        serialPort->close();
        ui->btnCloseOrOpen->setText("打开串口");
        ui->comboBox_databit->setEnabled(true); //使其失效
        ui->comboBox_fileCon->setEnabled(true); //使其失效
        ui->comboBox_jiaoyan->setEnabled(true); //使其失效
        ui->comboBox_stopbit->setEnabled(true); //使其失效
        ui->comboBox_boautrate->setEnabled(true); //使其失效
        ui->comboBox_serialNum->setEnabled(true); //使其失效
        ui->btnSendContext->setEnabled(false);
        serialStatus = false;
    }
}

  3.4 串口调试助手实现自发自收功能

	发送:通过发送控件转到槽,编写槽函数,
void Widget::on_btnSendContext_clicked()
{
    int writeCnt = 0;
    const char* sendata = ui->lineEditSendContext->text().toStdString().c_str();    //从ui控件上获取发送的数据
    writeCnt = serialPort->write(sendata); //将数据写入串口,成功返回写入字节数,失败返回-1

    if(writeCnt == -1){
        ui->labelSendStatus->setText("SendError!");
    }else{
        writeCntTotal += writeCnt;
        ui->labelSendStatus->setText("SendOK!");
        ui->labelSendcnt->setNum(writeCntTotal);
        //记录不显示重复字符
        if(strcmp(sendata,SenderBak.toStdString().c_str()) != 0){   //str1 < str2 返回负数 ,str1 = str2返回0, str1 > str2 返回正数
            ui->textEditRecord->append(sendata);
            SenderBak =  QString(sendata);
        }
    }
}
接收:
	首先要实现自发自收功能要绑定信号与槽
	connect(serialPort,&QSerialPort::readyRead,this,&Widget::on_serialData_reached);
	信号:QSerialPort::readyRead
	槽(自定义):Widget::on_serialData_reached

void Widget::on_serialData_reached()
{
    QString revMessage =  serialPort->readAll();    //读取串口
    if(revMessage != NULL){
        readCntTotal += revMessage.size();
        qDebug() << "getMessage: "<< revMessage;
        ui->textEditRev->append(revMessage);
        ui->labelRevcnt->setNum(readCntTotal);
    }
}


  3.5 串口调试助手实现自动发送功能(QTimer)

    timer = new QTimer(this); //为整个窗口添加一个定时器
 	
 	connect(timer,&QTimer::timeout,this,[=](){
        on_btnSendContext_clicked();
    });	//绑定timer信号,到点就发送

void Widget::on_checkBoxSendInTime_clicked(bool checked)
{
    if(checked){
        ui->lineEditTimeeach->setEnabled(false);
        ui->lineEditSendContext->setEnabled(false);
        timer->start(ui->lineEditTimeeach->text().toUInt()); //设置
    }else{
        timer->stop();
        ui->lineEditTimeeach->setEnabled(true);
        ui->lineEditSendContext->setEnabled(true);
    }
}

  3.6 串口调试助手保存清空接收按键

void Widget::on_btnrevClear_clicked()
{
    ui->textEditRev->clear();
}

void Widget::on_btnrevSave_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                                    "C:/Users/qzh/Desktop/serialData.txt",
                                                    tr("Text files(*.txt)"));
    if(fileName != NULL){
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
            return;

        QTextStream out(&file);
        out << ui->textEditRev->toPlainText();
        file.close();
    }
}

  3.7 获取当前系统时间(QDateTime)

//设置定时器触发
    QTimer *getSysTimer = new QTimer(this);
    connect(getSysTimer,SIGNAL(timeout()),this,SLOT(time_reflash()));   //绑定定时器刷新时间-通过高频率获取和显示达到时间更新效果
    getSysTimer->start(100);
//获取当前时间
void Widget::getSysTime()
{
    QDateTime currentDateTime = QDateTime::currentDateTime();
    QDate date = currentDateTime.date();
    int year = date.year();
    int month = date.month();
    int day = date.day();

    QTime time = currentDateTime.time();
    int hour = time.hour();
    int minute = time.minute();
    int second = time.second();

    //QString myTime = QString("%1-%2-%3 %4:%5:%6", year,month,day,hour,time.minute(),time.second());
    //占位符构造QString 类型

    myTime = QString("%1-%2-%3 %4:%5:%6")
            .arg(year,2,10,QChar('0'))
            .arg(month,2,10,QChar('0'))
            .arg(day,2,10,QChar('0'))
            .arg(hour,2,10,QChar('0'))
            .arg(minute,2,10,QChar('0'))
            .arg(second,2,10,QChar('0'));
    ui->labelCurrentTime->setText(myTime);
    ui->labelCurrentTime->setText(myTime);
}
//更新时间
void Widget::time_reflash()
{
    getSysTime();
}

  3.8 接收时间并显示

1:
	在头文件中设置时间标志位
    bool timeFlag = false;
    
void Widget::on_serialData_reached()    //读取串口数据
{

    QString revMessage =  serialPort->readAll();    //读取串口
    if(revMessage != NULL){
        readCntTotal += revMessage.size();
        qDebug() << "getMessage: "<< revMessage;
        if(!timeFlag){
            ui->textEditRev->append(revMessage);
        }else{
            QString mes = "[" +myTime +"]" + revMessage;
            ui->textEditRev->append(mes);

        }
        ui->labelRevcnt->setText("Received:" + QString::number(readCntTotal));
    }
}


void Widget::on_checkBoxRevTime_clicked(bool checked)
{
    if(checked){
        timeFlag = true;
    }else{
        timeFlag = false;
    }
}
2:ui->checkBoxRevTime->checkState()
void Widget::on_serialData_reached()    //读取串口数据
{

    QString revMessage =  serialPort->readAll();    //读取串口
    if(revMessage != NULL){
        qDebug() << "getMessage: "<< revMessage;
        if(ui->checkBoxRevTime->checkState() == Qt::Unchecked){
            ui->textEditRev->append(revMessage);
        }else if(ui->checkBoxRevTime->checkState() == Qt::Checked){
            QString mes = "[" +myTime +"]" + revMessage;
            ui->textEditRev->append(mes);
        }
        readCntTotal += revMessage.size();
        ui->labelRevcnt->setText("Received:" + QString::number(readCntTotal));
    }
}

  3.9 HEX显示(QByteArray)(to编码,from解码)

在这里插入图片描述

void Widget::on_checkBoxHexDisplay_clicked(bool checked)
{
    if(checked){
        //1.读取textEdit的内容
        QString tmp = ui->textEditRev->toPlainText();

        //2.转换成HEX显示
        QByteArray qtmp = tmp.toUtf8();   //QString的a(UTF-8)转换成 QByteArray的a(UTF-8)
        qtmp = qtmp.toHex();              //QByteArray的a(UTF-8)转换成 QByteArray的61(HEX)   --  编码

        //3.显示
        QString lastShow;
        tmp = QString::fromUtf8(qtmp);
        for(int i=0; i <tmp.size();i+=2){
            lastShow += tmp.mid(i,2) + " "; //tmp.mid(i,2) -- 获得tmp字符第i个字符之后的两个字符
        }
        ui->textEditRev->setText(lastShow.toUpper());  //QByteArray HEX的61  转换成QString 61    //toUpper()大写显示
    }else{

        //1.读取textEdit内容 .hex
        QString tmpHexString = ui->textEditRev->toPlainText();
        QByteArray tmpHexQByteArry = tmpHexString.toUtf8();     //QString 61(HEX) 转换成QByteArray 61(UTF-8)
        QByteArray tmpQByteString = QByteArray::fromHex(tmpHexQByteArry);       //QByteArray的61 转成QByteArray的a -- 解码
        ui->textEditRev->setText(QString::fromUtf8(tmpQByteString));    //QByteArray转换成字符串
    }

}

  3.10 串口调试助手,发送HEX发送

void Widget::on_btnSendContext_clicked()    //发送串口数据
{
    int writeCnt = 0;
    const char* sendata = ui->lineEditSendContext->text().toLocal8Bit().constData();    //从ui控件上获取发送的数据
    if(ui->checkBoxHexSend->isChecked()){	//检查HEX发送是否被勾选
        QString tmp = ui->lineEditSendContext->text();
        //判断是否是偶数位
        QByteArray tmpArry = tmp.toLocal8Bit();
        if(tmpArry.size() % 2 != 0){
            ui->labelSendStatus->setText("ErroR Input");
            return;
        }
        //判断是否是符合十六进制表达
        for(char c : tmpArry){
            if(!std::isxdigit(c)){  //判断每一个字符是否是十六进制
                ui->labelSendStatus->setText("ErroR Input");
                return;
            }
        }
        //转换成16进制发送,用书输入1,变成1,拒绝变成字符1 ,ASCII:49
        QByteArray arrySend = QByteArray::fromHex(tmpArry);
        writeCnt = serialPort->write(arrySend); //将数据写入串口,成功返回写入字节数,失败返回-1
    }else{

        writeCnt = serialPort->write(sendata); //将数据写入串口,成功返回写入字节数,失败返回-1

        if(writeCnt == -1){
            ui->labelSendStatus->setText("SendError!");
        }else{
            writeCntTotal += writeCnt;
            ui->labelSendStatus->setText("SendOK!");
            //ui->labelSendcnt->setNum(writeCntTotal);
            ui->labelSendcnt->setText("Sent:" + QString::number(writeCntTotal));
            //记录不显示重复字符
            if(strcmp(sendata,SenderBak.toStdString().c_str()) != 0){   //str1 < str2 返回负数 ,str1 = str2返回0, str1 > str2 返回正数
                ui->textEditRecord->append(sendata);
                SenderBak =  QString::fromUtf8(sendata);

            }
        }
    }
}

  3.11 串口调试助手添加换行功能

// 接收和发送两端同步
void Widget::on_btnSendContext_clicked()    //发送串口数据
{
    int writeCnt = 0;
    const char* sendata = ui->lineEditSendContext->text().toLocal8Bit().constData();    //从ui控件上获取发送的数据
    if(ui->checkBoxHexSend->isChecked()){
        QString tmp = ui->lineEditSendContext->text();
        //判断是否是偶数位
        QByteArray tmpArry = tmp.toLocal8Bit();
        if(tmpArry.size() % 2 != 0){
            ui->labelSendStatus->setText("ErroR Input");
            return;
        }
        //判断是否是符合十六进制表达
        for(char c : tmpArry){
            if(!std::isxdigit(c)){  //判断每一个字符是否是十六进制
                ui->labelSendStatus->setText("ErroR Input");
                return;
            }
        }
        if(ui->checkBoxSendNewLine->isChecked())    //发送新行
            tmpArry.append("\r\n");
        //转换成16进制发送,用书输入1,变成1,拒绝变成字符1 ,ASCII:49
        QByteArray arrySend = QByteArray::fromHex(tmpArry);
        writeCnt = serialPort->write(arrySend); //将数据写入串口,成功返回写入字节数,失败返回-1
    }else{
        if(ui->checkBoxSendNewLine->isChecked()){
            QByteArray arrySendData(sendata,strlen(sendata));
            arrySendData.append("\r\n");
            writeCnt = serialPort->write(arrySendData);
        }else
            writeCnt = serialPort->write(sendata); //将数据写入串口,成功返回写入字节数,失败返回-1
    }

    //发送失败的清空
    if(writeCnt == -1){
        ui->labelSendStatus->setText("SendError!");
    }else{
        writeCntTotal += writeCnt;
        ui->labelSendStatus->setText("SendOK!");
        //ui->labelSendcnt->setNum(writeCntTotal);
        ui->labelSendcnt->setText("Sent:" + QString::number(writeCntTotal));
        //记录不显示重复字符
        if(strcmp(sendata,SenderBak.toStdString().c_str()) != 0){   //str1 < str2 返回负数 ,str1 = str2返回0, str1 > str2 返回正数
            ui->textEditRecord->append(sendata);
            SenderBak =  QString::fromUtf8(sendata);

        }
    }
}


void Widget::on_serialData_reached()    //读取串口数据
{

    QString revMessage =  serialPort->readAll();    //读取串口
    if(revMessage != NULL){
        if(ui->checkBoxLine->isChecked()) revMessage.append("\r\n");    //自动换行被按下
        if(ui->checkBoxHexDisplay->isChecked()){
            QByteArray tmpHexString = revMessage.toUtf8().toHex();  //将缓存的内容(新发的内容)转成HEX
            //原来旧的内容先读出来
            QString tmpStringHex = ui->textEditRev->toPlainText();  //保存旧的内容
            tmpHexString = tmpStringHex.toUtf8() + tmpHexString;    //旧的内容转成QByteArry类型+新的内容
            ui->textEditRev->setText(QString::fromUtf8(tmpHexString));
        }else{
            qDebug() << "getMessage: "<< revMessage;
            if(ui->checkBoxRevTime->checkState() == Qt::Unchecked){
                ui->textEditRev->insertPlainText(revMessage);
            }else if(ui->checkBoxRevTime->checkState() == Qt::Checked){
                QString mes = "[" +myTime +"]" + revMessage;
                ui->textEditRev->insertPlainText(mes); //不换行添加
            }
            readCntTotal += revMessage.size();
            ui->labelRevcnt->setText("Received:" + QString::number(readCntTotal));
        }
    }
}

  3.12 隐藏和显示

void Widget::on_btnHideTable_clicked(bool checked)
{
    if(checked){
        ui->btnHideTable->setText("拓展面板");
        ui->groupBoxTexts->hide();
    }else{
        ui->btnHideTable->setText("隐藏面板");
        ui->groupBoxTexts->show();
    }
}

void Widget::on_btnHideHistory_clicked(bool checked)
{
    if(checked){
        ui->btnHideHistory->setText("显示历史");
        ui->groupBoxRecord->hide();
    }else{
        ui->btnHideHistory->setText("隐藏历史");
        ui->groupBoxRecord->show();
    }
}

  3.13 自定义ComboBox完成串口号列表的刷新

	将QComboBox提升为MyComboBox
	自定义信号与槽
	重写鼠标点击事件
	事件关联

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  3.14 通过子控件组控制子控件(相同类型)(通过设置属性传参)

/*
	1.构造子控件名字
	2.通过名字找到相应子控件
	3.设置子控件id
	4.进行信号与槽的绑定
*/

    QList<QPushButton *> buttons;   //构建QPushButton数组
    for(int i=1; i<=9; i++){
        QString btnName = QString("pushButton_%1").arg(i);  //设置按钮名字
        QPushButton* btn = findChild<QPushButton *>(btnName);  //找到相应得子控件
        if(btn){
            btn->setProperty("buttonId",i); //设置buttonId为i
            buttons.append(btn);
            connect(btn,SIGNAL(clicked()),this,SLOT(on_command_button_clicked()));  //绑定信号与槽
        }
    }

槽:
/*
	1.获得相应发送信号的控件
	2.进行槽函数功能的编写
*/
void Widget::on_command_button_clicked()
{

    QPushButton *btn = qobject_cast<QPushButton *>(sender());   //获得发送信号的对象的名字,并返回QPushButton类型
    if(btn){
        int num = btn->property("buttonId").toInt();
        qDebug() << num;
        QString lineEditName = QString("lineEdit_%1").arg(num); //构建匹配的发送文本的名字
        QLineEdit *lineEide = findChild<QLineEdit *>(lineEditName); //找到对应名字的子控件
        if(lineEide){
            ui->lineEditSendContext->setText(lineEide->text());
        }

        QString checkBoxName = QString("checkBox_%1").arg(num);
        QCheckBox *checkBox = findChild<QCheckBox *>(checkBoxName);
        if(checkBox){
            ui->checkBoxHexSend->setChecked(checkBox->isChecked()); //设置checkBoxHexSend控件的状态
        }
        on_btnSendContext_clicked();    //发送数据
    }
}

  3.15 定时器循环发送

/*
	Qt的ui界面本身有自己的线程,通过对ui界面本身的线程进行操作会出现问题,
	如对进行sleep操作,ui整个界面会停止刷新所以不能在qt的ui线程中延时,否则导致页面的刷新问题,所以有以下两种方法解决问题
    法1:定时器---QTimer
    法2:多线程---QThread-
    	缺点:线程是写死的
*/

   3.15.1 定时器(QTimer)

定义全局变量:
    QTimer *buttonsConTimer;
	int buttonIndex
初始化绑定信号与槽
    buttonsConTimer = new QTimer(this);
    connect(buttonsConTimer,&QTimer::timeout,this,&Widget::buttons_handler);
//槽函数-通过定时周期性触发
void Widget::buttons_handler()
{
    if(buttonIndex < buttons.size()){
        QPushButton *btnTmp = buttons[buttonIndex];
        emit btnTmp->clicked();   //手动触发按键
        buttonIndex++;
    }else{
        buttonIndex = 0;
    }
}

//定时器开关通过检测checkBox状态
void Widget::on_checkBox_send_clicked(bool checked)
{
    if(checked){
        ui->spinBox->setEnabled(false);
        buttonsConTimer->start(ui->spinBox->text().toUInt());   //打开定时器
    }else{
        ui->spinBox->setEnabled(true);
        buttonsConTimer->stop();       //关闭定时器
    }
}

   3.15.2 多线程(QThread-重写run函数)

	逻辑与定时器一致,只不过从定时器操作变成了线程操作
	需要重写run()函数,所以定义了一个新的QThread类继承于QThread

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  3.16 重置按键对话框定制

    QList<QPushButton *> buttons;   //构建QPushButton数组
    QList<QLineEdit *> lineEdits;   //构建QLineEdit数组
    QList<QCheckBox *> checkBoxs;   //构建QCheckBox数组
	//初始化
    for(int i=1; i<=9; i++){
        QString btnName = QString("pushButton_%1").arg(i);  //设置按钮名字
        QPushButton* btn = findChild<QPushButton *>(btnName);  //找到相应得子控件
        if(btn){
            btn->setProperty("buttonId",i); //设置buttonId为i
            buttons.append(btn);
            connect(btn,SIGNAL(clicked()),this,SLOT(on_command_button_clicked()));  //绑定信号与槽
        }

        QString lineEditName = QString("lineEdit_%1").arg(i);
        QLineEdit *LineEdit = findChild<QLineEdit *>(lineEditName);
        lineEdits.append(LineEdit);

        QString checkBoxName = QString("checkBox_%1").arg(i);
        QCheckBox *checkBox = findChild<QCheckBox *>(checkBoxName);
        checkBoxs.append(checkBox);
    }


void Widget::on_btnInit_clicked()
{
    QMessageBox msgBox;
    msgBox.setWindowTitle("提示");
    msgBox.setIcon(QMessageBox::Question);
    msgBox.setText("重置列表不可逆确认是否重置");
    //msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
    QPushButton *yesButton = msgBox.addButton("是",QMessageBox::YesRole);
    QPushButton *noButton = msgBox.addButton("否",QMessageBox::NoRole);
    msgBox.exec();
    if(msgBox.clickedButton() == yesButton){

        for(int i=0;i<lineEdits.size();i++){
            //遍历lineEdit,并清空
            lineEdits[i]->clear();
            //遍历CheckBox,并取消勾选
            checkBoxs[i]->setChecked(false);
        }
    }
    if(msgBox.clickedButton() == noButton){

    }
}

  3.17 保存

void Widget::on_btnSave_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                                    "C:/Users/qzh/Desktop",
                                                    tr("Text files (*.txt)"));
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        return;
    QTextStream out(&file);
    for(int i=0; i<lineEdits.size(); i++){
        out << checkBoxs[i]->isChecked() << "," <<lineEdits[i]->text() << "\n";
    }
    file.close();
}

  3.18 载入

void Widget::on_btnLoad_clicked()
{
    int i = 0;
    QString fileName = QFileDialog::getOpenFileName(this, tr("打开文件"),
                                                    "C:/Users/qzh/Desktop",
                                                    tr("Text files (*.txt)"));
    if(fileName != NULL){
        QFile file(fileName);
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
            return;
        QTextStream in(&file);
        while(!in.atEnd() && i < lineEdits.size()){
            QString line = in.readLine();
            QStringList parts = line.split(",");    //split按,分割成两部分,前半部分parts[0]- checkbox状态和后半部分parts[1]- 内容
            if(parts.count() == 2){
                checkBoxs[i]->setChecked(parts[0].toInt());
                lineEdits[i]->setText(parts[1]);
            }
            i++;
        }
    }
}

 4. 打包

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

	找到qt的bin文件安装路径例(我的):D:\qt\5.12.9\mingw73_32\bin

在这里插入图片描述

win+r 打开cmd


进入打包的文件所在的位置:
	E:\qtproject\2-Chuankou\build-1-Serial-001-ui-Desktop_Qt_5_12_9_MinGW_32_bit-Release\release


执行:D:\qt\5.12.9\mingw73_32\bin\windeployqt.exe + 生成的.exe
例:D:\qt\5.12.9\mingw73_32\bin\windeployqt.exe 1-Serial-001-ui.exe

在这里插入图片描述

	最后将以下文件复制添加到release中

在这里插入图片描述
在这里插入图片描述

 5. 总结-代码整合

在这里插入图片描述

  5.1 头文件

文件名:customthread.h
内容:
#ifndef CUSTOMTHREAD_H
#define CUSTOMTHREAD_H

#include <QThread>
#include <QWidget>

class CustomThread : public QThread
{
    Q_OBJECT
public:
    CustomThread(QWidget *parent = nullptr);
protected:
    void run() override;
signals:
    void threadTimeOut();
};

#endif // CUSTOMTHREAD_H

文件名:mycombobox.h
内容:

#ifndef MYCOMBOBOX_H
#define MYCOMBOBOX_H
#include <QComboBox>


class MyComboBox : public QComboBox
{
    Q_OBJECT //发送信号的宏
public:
    MyComboBox(QWidget *parent = nullptr);

protected:
    void mousePressEvent(QMouseEvent *e) override;

signals:
    void refresh();
};

#endif // MYCOMBOBOX_H

文件名:widget.h
内容:

#ifndef WIDGET_H
#define WIDGET_H
#include <QSerialPortInfo>
#include <QDebug>
#include <QWidget>
#include <QSerialPort>
#include <QTimer>
#include <QPushButton>
#include "customthread.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QTime>
#include <QByteArray>
#include <QThread>
#include  "mycombobox.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_btnCloseOrOpen_clicked();

    void on_btnSendContext_clicked();

    void on_serialData_reached();

    void on_btnCloseOrOpen_clicked(bool checked);

    void on_checkBoxSendInTime_clicked(bool checked);

    void on_btnrevClear_clicked();

    void on_btnrevSave_clicked();
    void time_reflash();

    void on_checkBoxHexDisplay_clicked(bool checked);

    void on_btnHideTable_clicked(bool checked);

    void on_btnHideHistory_clicked(bool checked);
    void refreshSerialName();

    void on_command_button_clicked();

    void on_checkBox_send_clicked(bool checked);
    void buttons_handler();

    void on_btnInit_clicked();

    void on_btnSave_clicked();

    void on_btnLoad_clicked();

private:
    Ui::Widget *ui;
    QSerialPort *serialPort;
    int writeCntTotal;
    int readCntTotal;
    QString SenderBak;
    bool serialStatus = false;  //打开关闭标志位
    QTimer *timer;
    QString myTime;
    void getSysTime();
    QTimer *buttonsConTimer;
    QList<QPushButton *> buttons;   //构建QPushButton数组
    QList<QLineEdit *> lineEdits;   //构建QLineEdit数组
    QList<QCheckBox *> checkBoxs;   //构建QCheckBox数组
    int buttonIndex;

    CustomThread *myThread;
};
#endif // WIDGET_H

  5.1 .cpp

文件名:customthread.h
内容:

#include "customthread.h"


CustomThread::CustomThread(QWidget *parent) : QThread(parent)
{

}

void CustomThread::run()
{
    while(true){
        msleep(1000);
        emit threadTimeOut();
    }
}


文件名:main.h
内容:

#include "widget.h"

#include <QApplication>

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

文件名:mycombobox.cpp
内容:


#include "mycombobox.h"

#include <QMouseEvent>

MyComboBox::MyComboBox(QWidget *parent) : QComboBox(parent)
{

}

void MyComboBox::mousePressEvent(QMouseEvent *e)
{
    //发送信号
    if(e->button() == Qt::LeftButton){
        emit refresh();
    }
    QComboBox::mousePressEvent(e);
}

文件名:widget.cpp
内容:

#include "widget.h"
#include "ui_widget.h"




Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    //设置布局
    ui->setupUi(this);
    this->setLayout(ui->gridLayoutGlobal);


    //实例化一个串口对象
    serialPort = new QSerialPort(this);
    timer = new QTimer(this); //为整个窗口添加一个定时器



    buttonsConTimer = new QTimer(this);
    connect(buttonsConTimer,&QTimer::timeout,this,&Widget::buttons_handler);

    buttonIndex = 0;
    writeCntTotal = 0;
    readCntTotal = 0;

    //    //定时器
    //    QTimer *getSysTimer = new QTimer(this);
    //    connect(getSysTimer,SIGNAL(timeout()),this,SLOT(time_reflash()));   //绑定定时器刷新时间
    //    getSysTimer->start(100);

    //线程触发
    myThread = new CustomThread(this);
    connect(myThread,&CustomThread::threadTimeOut,this,&Widget::buttons_handler);



    connect(serialPort,&QSerialPort::readyRead,this,&Widget::on_serialData_reached);    //绑定接收
    connect(timer,&QTimer::timeout,this,[=](){
        on_btnSendContext_clicked();
    }); //定时发送

    connect(ui->comboBox_serialNum,&MyComboBox::refresh,this,&Widget::refreshSerialName);
    //设置打开界面默认参数
    ui->comboBox_boautrate->setCurrentIndex(6);
    ui->comboBox_databit->setCurrentIndex(3);
    ui->btnSendContext->setEnabled(false);
    ui->checkBoxSendInTime->setEnabled(false);
    ui->checkBoxSendNewLine->setEnabled(false);
    ui->checkBoxHexSend->setEnabled(false);
    ui->btnSave->setEnabled(false);
    ui->btnInit->setEnabled(false);
    ui->btnLoad->setEnabled(false);

    //获取可用串口
    //[static] QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
    refreshSerialName();
    ui->labelSendStatus->setText(ui->comboBox_serialNum->currentText() + "  Not Open");


    for(int i=1; i<=9; i++){
        QString btnName = QString("pushButton_%1").arg(i);  //设置按钮名字
        QPushButton* btn = findChild<QPushButton *>(btnName);  //找到相应得子控件
        if(btn){
            btn->setProperty("buttonId",i); //设置buttonId为i
            buttons.append(btn);
            connect(btn,SIGNAL(clicked()),this,SLOT(on_command_button_clicked()));  //绑定信号与槽
        }

        QString lineEditName = QString("lineEdit_%1").arg(i);
        QLineEdit *LineEdit = findChild<QLineEdit *>(lineEditName);
        lineEdits.append(LineEdit);

        QString checkBoxName = QString("checkBox_%1").arg(i);
        QCheckBox *checkBox = findChild<QCheckBox *>(checkBoxName);
        checkBoxs.append(checkBox);
    }
}

Widget::~Widget()
{
    delete ui;
}


/*
 * --首先实例化串口对象而后配置串口参数
    1.选择端口号
    2.配置波特率
    3.配置数据位
    4.配置校验位
    5.配置停止位
    6.流控
*/

/*
    enum Parity {
        NoParity = 0,
        EvenParity = 2,
        OddParity = 3,
        SpaceParity = 4,
        MarkParity = 5,
        UnknownParity = -1
    };
*/
void Widget::on_btnCloseOrOpen_clicked()
{
    /*
    if(!serialStatus){  //打开时
        //1.选择端口号
        serialPort->setPortName(ui->comboBox_serialNum->currentText());
        //2.配置波特率
        serialPort->setBaudRate(ui->comboBox_boautrate->currentText().toInt());
        //3.配置数据位
        serialPort->setDataBits(QSerialPort::DataBits(
                                    ui->comboBox_databit->currentText().toUInt()));
        //4.配置校验位
        switch (ui->comboBox_jiaoyan->currentIndex()) {
        case 0:
            serialPort->setParity(QSerialPort::NoParity);
            break;
        case 1:
            serialPort->setParity(QSerialPort::EvenParity);
            break;
        case 2:
            serialPort->setParity(QSerialPort::MarkParity);
            break;
        case 3:
            serialPort->setParity(QSerialPort::OddParity);
            break;
        case 4:
            serialPort->setParity(QSerialPort::SpaceParity);
            break;
        default:
            serialPort->setParity(QSerialPort::UnknownParity);
            break;

        }
        //5.配置停止位
        serialPort->setStopBits(QSerialPort::StopBits(
                                    ui->comboBox_stopbit->currentText().toUInt()));
        //6.配置流控
        if(ui->comboBox_fileCon->currentText() == "None"){
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
        }
        //7.打开串口
        if(serialPort->open(QIODevice::ReadWrite)){ //打开状态
            qDebug() << "serial open success";
            ui->comboBox_databit->setEnabled(false); //使其失效
            ui->comboBox_fileCon->setEnabled(false); //使其失效
            ui->comboBox_jiaoyan->setEnabled(false); //使其失效
            ui->comboBox_stopbit->setEnabled(false); //使其失效
            ui->comboBox_boautrate->setEnabled(false); //使其失效
            ui->comboBox_serialNum->setEnabled(false); //使其失效
            ui->btnCloseOrOpen->setText(QString("关闭串口"));
            ui->btnSendContext->setEnabled(true);
            serialStatus = true;
        }else{  //打开失败
            QMessageBox msgBox;
            msgBox.setWindowTitle("打开串口错误");
            msgBox.setText("打开失败,串口可能被占用.");
            msgBox.exec();
        }
    }else{  //关闭时
        serialPort->close();
        ui->btnCloseOrOpen->setText("打开串口");
        ui->comboBox_databit->setEnabled(true); //使其失效
        ui->comboBox_fileCon->setEnabled(true); //使其失效
        ui->comboBox_jiaoyan->setEnabled(true); //使其失效
        ui->comboBox_stopbit->setEnabled(true); //使其失效
        ui->comboBox_boautrate->setEnabled(true); //使其失效
        ui->comboBox_serialNum->setEnabled(true); //使其失效
        ui->btnSendContext->setEnabled(false);
        serialStatus = false;
    }*/
}

void Widget::on_btnSendContext_clicked()    //发送串口数据
{
    int writeCnt = 0;
    const char* sendata = ui->lineEditSendContext->text().toLocal8Bit().constData();    //从ui控件上获取发送的数据
    if(ui->checkBoxHexSend->isChecked()){
        QString tmp = ui->lineEditSendContext->text();
        //判断是否是偶数位
        QByteArray tmpArry = tmp.toLocal8Bit();
        if(tmpArry.size() % 2 != 0){
            ui->labelSendStatus->setText("ErroR Input");
            return;
        }
        //判断是否是符合十六进制表达
        for(char c : tmpArry){
            if(!std::isxdigit(c)){  //判断每一个字符是否是十六进制
                ui->labelSendStatus->setText("ErroR Input");
                return;
            }
        }
        if(ui->checkBoxSendNewLine->isChecked())    //发送新行
            tmpArry.append("\r\n");
        //转换成16进制发送,用书输入1,变成1,拒绝变成字符1 ,ASCII:49
        QByteArray arrySend = QByteArray::fromHex(tmpArry);
        writeCnt = serialPort->write(arrySend); //将数据写入串口,成功返回写入字节数,失败返回-1
    }else{
        if(ui->checkBoxSendNewLine->isChecked()){
            QByteArray arrySendData(sendata,strlen(sendata));
            arrySendData.append("\r\n");
            writeCnt = serialPort->write(arrySendData);
        }else
            writeCnt = serialPort->write(sendata); //将数据写入串口,成功返回写入字节数,失败返回-1
    }

    //发送失败的清空
    if(writeCnt == -1){
        ui->labelSendStatus->setText("SendError!");
    }else{
        writeCntTotal += writeCnt;
        ui->labelSendStatus->setText("SendOK!");
        //ui->labelSendcnt->setNum(writeCntTotal);
        ui->labelSendcnt->setText("Sent:" + QString::number(writeCntTotal));
        //记录不显示重复字符
        if(strcmp(sendata,SenderBak.toStdString().c_str()) != 0){   //str1 < str2 返回负数 ,str1 = str2返回0, str1 > str2 返回正数
            ui->textEditRecord->append(sendata);
            SenderBak =  QString::fromUtf8(sendata);

        }
    }


}

void Widget::on_serialData_reached()    //读取串口数据
{

    QString revMessage =  serialPort->readAll();    //读取串口
    if(revMessage != NULL){
        if(ui->checkBoxLine->isChecked()) revMessage.append("\r\n");    //自动换行被按下
        if(ui->checkBoxHexDisplay->isChecked()){
            QByteArray tmpHexString = revMessage.toUtf8().toHex().toUpper();  //将缓存的内容(新发的内容)转成HEX
            //原来旧的内容先读出来
            QString tmpStringHex = ui->textEditRev->toPlainText();  //保存旧的内容
            tmpHexString = tmpStringHex.toUtf8() + tmpHexString;    //旧的内容转成QByteArry类型+新的内容
            ui->textEditRev->setText(QString::fromUtf8(tmpHexString));
        }else{
            qDebug() << "getMessage: "<< revMessage;
            if(ui->checkBoxRevTime->checkState() == Qt::Unchecked){
                ui->textEditRev->insertPlainText(revMessage);
            }else if(ui->checkBoxRevTime->checkState() == Qt::Checked){
                QString mes = "[" +myTime +"]" + revMessage;
                ui->textEditRev->insertPlainText(mes); //不换行添加
            }

        }
        readCntTotal += revMessage.size();
        ui->labelRevcnt->setText("Received:" + QString::number(readCntTotal));

        ui->textEditRev->moveCursor(QTextCursor::End);	//将光标移动至尾部
        ui->textEditRev->ensureCursorVisible();
        //ui->textEditRev->setFocus();
    }
}

void Widget::on_btnCloseOrOpen_clicked(bool checked)
{
    if(checked){  //打开时
        //1.选择端口号
        serialPort->setPortName(ui->comboBox_serialNum->currentText());
        //2.配置波特率
        serialPort->setBaudRate(ui->comboBox_boautrate->currentText().toInt());
        //3.配置数据位
        serialPort->setDataBits(QSerialPort::DataBits(
                                    ui->comboBox_databit->currentText().toUInt()));
        //4.配置校验位
        switch (ui->comboBox_jiaoyan->currentIndex()) {
        case 0:
            serialPort->setParity(QSerialPort::NoParity);
            break;
        case 1:
            serialPort->setParity(QSerialPort::EvenParity);
            break;
        case 2:
            serialPort->setParity(QSerialPort::MarkParity);
            break;
        case 3:
            serialPort->setParity(QSerialPort::OddParity);
            break;
        case 4:
            serialPort->setParity(QSerialPort::SpaceParity);
            break;
        default:
            serialPort->setParity(QSerialPort::UnknownParity);
            break;

        }
        //5.配置停止位
        serialPort->setStopBits(QSerialPort::StopBits(
                                    ui->comboBox_stopbit->currentText().toUInt()));
        //6.配置流控
        if(ui->comboBox_fileCon->currentText() == "None"){
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
        }
        //7.打开串口
        if(serialPort->open(QIODevice::ReadWrite)){ //打开状态
            qDebug() << "serial open success";
            ui->comboBox_databit->setEnabled(false); //使其失效
            ui->comboBox_fileCon->setEnabled(false); //使其失效
            ui->comboBox_jiaoyan->setEnabled(false); //使其失效
            ui->comboBox_stopbit->setEnabled(false); //使其失效
            ui->comboBox_boautrate->setEnabled(false); //使其失效
            ui->comboBox_serialNum->setEnabled(false); //使其失效

            ui->btnCloseOrOpen->setText(QString("关闭串口"));
            ui->btnSendContext->setEnabled(true);
            ui->checkBoxSendInTime->setEnabled(true);
            ui->checkBoxSendNewLine->setEnabled(true);
            ui->checkBoxHexSend->setEnabled(true);
            ui->btnSave->setEnabled(true);
            ui->btnInit->setEnabled(true);
            ui->btnLoad->setEnabled(true);
            // serialStatus = true;
            ui->labelSendStatus->setText(ui->comboBox_serialNum->currentText() + "   isOpen");
        }else{  //打开失败
            QMessageBox msgBox;
            msgBox.setWindowTitle("打开串口错误");
            msgBox.setText("打开失败,串口可能被占用.");
            msgBox.exec();
        }
    }else{  //关闭时
        serialPort->close();
        ui->btnCloseOrOpen->setText("打开串口");
        ui->comboBox_databit->setEnabled(true); //使其失效
        ui->comboBox_fileCon->setEnabled(true); //使其失效
        ui->comboBox_jiaoyan->setEnabled(true); //使其失效
        ui->comboBox_stopbit->setEnabled(true); //使其失效
        ui->comboBox_boautrate->setEnabled(true); //使其失效
        ui->comboBox_serialNum->setEnabled(true); //使其失效
        ui->btnSendContext->setEnabled(false);
        ui->checkBoxSendInTime->setEnabled(false);
        ui->checkBoxSendNewLine->setEnabled(false);
        ui->checkBoxHexSend->setEnabled(false);
        ui->btnSave->setEnabled(false);
        ui->btnInit->setEnabled(false);
        ui->btnLoad->setEnabled(false);
        ui->checkBoxSendInTime->setCheckState(Qt::Unchecked);
        timer->stop();  //关闭定时器
        ui->lineEditTimeeach->setEnabled(true);
        ui->lineEditSendContext->setEnabled(true);

        // serialStatus = false;
        ui->labelSendStatus->setText(ui->comboBox_serialNum->currentText() + "   isClose");
    }
}

void Widget::on_checkBoxSendInTime_clicked(bool checked)
{
    if(checked){
        ui->lineEditTimeeach->setEnabled(false);
        ui->lineEditSendContext->setEnabled(false);
        timer->start(ui->lineEditTimeeach->text().toUInt()); //设置
    }else{
        timer->stop();
        ui->lineEditTimeeach->setEnabled(true);
        ui->lineEditSendContext->setEnabled(true);
    }
}

void Widget::on_btnrevClear_clicked()
{
    ui->textEditRev->clear();
}

void Widget::on_btnrevSave_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                                    "C:/Users/qzh/Desktop/serialData.txt",
                                                    tr("Text files(*.txt)"));
    if(fileName != NULL){
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
            return;

        QTextStream out(&file);
        out << ui->textEditRev->toPlainText();
        file.close();
    }
}

void Widget::time_reflash()
{
    getSysTime();
    ui->labelCurrentTime->setText(myTime);
}

void Widget::getSysTime()
{
    QDateTime currentDateTime = QDateTime::currentDateTime();
    QDate date = currentDateTime.date();
    int year = date.year();
    int month = date.month();
    int day = date.day();

    QTime time = currentDateTime.time();
    int hour = time.hour();
    int minute = time.minute();
    int second = time.second();

    //QString myTime = QString("%1-%2-%3 %4:%5:%6", year,month,day,hour,time.minute(),time.second());
    //占位符构造QString 类型

    myTime = QString("%1-%2-%3 %4:%5:%6")
            .arg(year,2,10,QChar('0'))
            .arg(month,2,10,QChar('0'))
            .arg(day,2,10,QChar('0'))
            .arg(hour,2,10,QChar('0'))
            .arg(minute,2,10,QChar('0'))
            .arg(second,2,10,QChar('0'));
}


void Widget::on_checkBoxHexDisplay_clicked(bool checked)
{
    if(checked){
        //1.读取textEdit的内容
        QString tmp = ui->textEditRev->toPlainText();

        //2.转换成HEX显示
        QByteArray qtmp = tmp.toUtf8();   //QString的a(UTF-8)转换成 QByteArray的a(UTF-8)
        qtmp = qtmp.toHex();              //QByteArray的a(UTF-8)转换成 QByteArray的61(HEX)   --  编码

        //3.显示
        QString lastShow;
        tmp = QString::fromUtf8(qtmp);
        for(int i=0; i <tmp.size();i+=2){
            lastShow += tmp.mid(i,2) + " "; //tmp.mid(i,2) -- 获得tmp字符第i个字符之后的两个字符
        }
        ui->textEditRev->setText(lastShow.toUpper());  //QByteArray HEX的61  转换成QString 61    //toUpper()大写显示
    }else{

        //1.读取textEdit内容 .hex
        QString tmpHexString = ui->textEditRev->toPlainText();
        QByteArray tmpHexQByteArry = tmpHexString.toUtf8();     //QString 61(HEX) 转换成QByteArray 61(UTF-8)
        QByteArray tmpQByteString = QByteArray::fromHex(tmpHexQByteArry);       //QByteArray的61 转成QByteArray的a -- 解码
        ui->textEditRev->setText(QString::fromUtf8(tmpQByteString));    //QByteArray转换成字符串
    }
    ui->textEditRev->moveCursor(QTextCursor::End);
    ui->textEditRev->ensureCursorVisible();

}

void Widget::on_btnHideTable_clicked(bool checked)
{
    if(checked){
        ui->btnHideTable->setText("拓展面板");
        ui->groupBoxTexts->hide();
    }else{
        ui->btnHideTable->setText("隐藏面板");
        ui->groupBoxTexts->show();
    }
}

void Widget::on_btnHideHistory_clicked(bool checked)
{
    if(checked){
        ui->btnHideHistory->setText("显示历史");
        ui->groupBoxRecord->hide();
    }else{
        ui->btnHideHistory->setText("隐藏历史");
        ui->groupBoxRecord->show();
    }
}

void Widget::refreshSerialName()
{
    ui->comboBox_serialNum->clear();
    //获取可用串口
    //[static] QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
    QList<QSerialPortInfo> serialList = QSerialPortInfo::availablePorts();  //获取可用的串口列表
    for(QSerialPortInfo serialinfo : serialList){   //迭代器迭代遍历
        qDebug() << serialinfo.portName();
        ui->comboBox_serialNum->addItem(serialinfo.portName()); //将可用的串口添加到串口中
    }
    ui->labelSendStatus->setText("Com Refresh");
}

void Widget::on_command_button_clicked()
{

    QPushButton *btn = qobject_cast<QPushButton *>(sender());   //获得发送信号的对象的名字,并返回QPushButton类型
    if(btn){
        int num = btn->property("buttonId").toInt();
        qDebug() << num;
        QString lineEditName = QString("lineEdit_%1").arg(num); //构建匹配的发送文本的名字
        QLineEdit *lineEide = findChild<QLineEdit *>(lineEditName); //找到对应名字的子控件
        if(lineEide){
            if(lineEide->text().size() <= 0) return;
            ui->lineEditSendContext->setText(lineEide->text());
        }

        QString checkBoxName = QString("checkBox_%1").arg(num);
        QCheckBox *checkBox = findChild<QCheckBox *>(checkBoxName);
        if(checkBox){
            ui->checkBoxHexSend->setChecked(checkBox->isChecked()); //设置checkBoxHexSend控件的状态
        }
        on_btnSendContext_clicked();    //发送数据
    }
}

void Widget::buttons_handler()
{
    if(buttonIndex < buttons.size()){
        QPushButton *btnTmp = buttons[buttonIndex];
        emit btnTmp->clicked();   //手动触发按键
        buttonIndex++;
    }else{
        buttonIndex = 0;
    }
}
/*
    不能在qt的ui线程中延时,否则导致页面的刷新问题
    法1:定时器
    法2:多线程
*/
void Widget::on_checkBox_send_clicked(bool checked)
{
    if(checked){
        ui->spinBox->setEnabled(false);
        myThread->start();
        //  buttonsConTimer->start(ui->spinBox->text().toUInt());   //打开定时器
    }else{
        ui->spinBox->setEnabled(true);
        myThread->terminate();
        //  buttonsConTimer->stop();       //关闭定时器
    }
}

void Widget::on_btnInit_clicked()
{
    QMessageBox msgBox;
    msgBox.setWindowTitle("提示");
    msgBox.setIcon(QMessageBox::Question);
    msgBox.setText("重置列表不可逆确认是否重置");
    //msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
    QPushButton *yesButton = msgBox.addButton("是",QMessageBox::YesRole);
    QPushButton *noButton = msgBox.addButton("否",QMessageBox::NoRole);
    msgBox.exec();
    if(msgBox.clickedButton() == yesButton){

        for(int i=0;i<lineEdits.size();i++){
            //遍历lineEdit,并清空
            lineEdits[i]->clear();
            //遍历CheckBox,并取消勾选
            checkBoxs[i]->setChecked(false);
        }
    }
    if(msgBox.clickedButton() == noButton){

    }
}

void Widget::on_btnSave_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("保存文件"),
                                                    "C:/Users/qzh/Desktop",
                                                    tr("Text files (*.txt)"));
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        return;
    QTextStream out(&file);
    for(int i=0; i<lineEdits.size(); i++){
        out << checkBoxs[i]->isChecked() << "," <<lineEdits[i]->text() << "\n";
    }
    file.close();
}

void Widget::on_btnLoad_clicked()
{
    int i = 0;
    QString fileName = QFileDialog::getOpenFileName(this, tr("打开文件"),
                                                    "C:/Users/qzh/Desktop",
                                                    tr("Text files (*.txt)"));
    if(fileName != NULL){
        QFile file(fileName);
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
            return;
        QTextStream in(&file);
        while(!in.atEnd() && i < lineEdits.size()){
            QString line = in.readLine();
            QStringList parts = line.split(",");    //split按,分割成两部分,前半部分parts[0]- checkbox状态和后半部分parts[1]- 内容
            if(parts.count() == 2){
                checkBoxs[i]->setChecked(parts[0].toInt());
                lineEdits[i]->setText(parts[1]);
            }
            i++;
        }
    }
}

链接:https://pan.baidu.com/s/1cKTUxDyDg6J7PcVLvj9Ltg 
提取码:nr0g 
--来自百度网盘超级会员V5的分享
  • 27
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值