目錄
一、前言
二、串口助手實現
2.1、串口
2.1.1、可用串口信息-QSerialPortInfo
?2.1.2、打開串口-QSerialPort
2.1.3、串口發送接收信息?
2.2、定時器-QTimer
2.3、常用屬性類型轉換(會更新)
2.4、子控件組規則命名優化
一、前言
這個是學習QT中實現的一個小項目——串口助手,這里是根據串口助手制作過程中所需要使用的類和插件制作的一個筆記,方便以后成為我們的技術庫,很方便于我們日后開發!? ? ? ? ? ? ? ? ? ? ? ? ? 串口助手模樣:
二、串口助手實現
2.1、串口
2.1.1、可用串口信息-QSerialPortInfo
每學習一個類,我們都需要去查手冊,查看它的成員還有使用前提,我們才能更好的使用起來:
說明需要添加:
?函數原型:
QList<QSerialPortInfo> QSerialPortInfo::availablePorts()QList<qint32> QSerialPortInfo::standardBaudRates()
我們使用上面這個類的這兩個函數就可以得到地電腦當前可使用的端口和波特率了,這里我們做個小demo將其打印出來:
#include <QSerialPortInfo>#include <QDebug> //顯示可用的串口端口QList<QSerialPortInfo> serialList = QSerialPortInfo::availablePorts();for(QSerialPortInfo serialInfo : serialList)//遍歷容器{qDebug() << serialInfo.portName();//打印可用的端口號ui->comboBox_serialNum->addItem(serialInfo.portName());//添加標簽}//顯示電腦可用的波特率QList<qint32> serialbotelv = QSerialPortInfo::standardBaudRates();for(qint32 serialbotelvInfo : serialbotelv)//遍歷容器{qDebug() << serialbotelvInfo;}
運行結果:
?2.1.2、打開串口-QSerialPort
使用一個串口需要配置很多參數,相同打開一個串口也需要提前配置好參數:
QSerialPort::QSerialPort(QObject *parent = nullptr)
用給定的父對象構造一個新的串行端口對象。
使用案例:
QSerialPort *serialPort;
serialPort = new QSerialPort(this);//為串口創建一個空間
構造好串口端口對象后,接下來就是配置參數了,配置參數的函數也不難找到,在類中的public Functions里面:找到函數后,再根據函數的參數找到對應自己組要的配置即可。
這里以配置數據位為代表:
bool setDataBits(QSerialPort::DataBits dataBits)
然后在看它的參數是DataBits類型,然后我們再去手冊查找?
找到公共類型點進去,找到自己要找的:?
最后再根據代碼邏輯實現即可:學習QT最重要的就是學會查手冊?
//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:break;serialPort->setParity(QSerialPort::EvenParity);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_databit->currentText().toUInt()));//6. 流控if(ui->comboBox_fileCon->currentText() == "None")serialPort->setFlowControl(QSerialPort::NoFlowControl);//7. 打開串口if(serialPort->open(QIODevice::ReadWrite)){qDebug() << "serial open success";}
運行結果:
2.1.3、串口發送接收信息?
發送信息:
const char* sendData = ui->lineEditSendContext->text().toStdString().c_str();
serialPort->write(sendData);//串口發送信息
qDebug() << "SendOK" << sendData;//打印信息驗證
ui->textEditRecord->append(sendData);//將發送的信息添加到歷史記錄文本里面
接收信息:
接收信息和單片機一樣,有信息來了就會有一股“感覺”來臨,這個“感覺”在QT中就是我們常用的信息了,我們要利用好這個感覺,感覺來了就處理!我們可以查看手冊這個類的信息有哪些?
發現這個類中沒有和接收信息相關的信息,所以我們要往上查,查他的父類(子承父業):?
所以我們還是老套路,綁定信號和槽,聲明定義槽函數:?(這里就不展示槽的聲明了)
//串口接收信號readyRead連接
connect(serialPort,&QSerialPort::readyRead,this,&Widget::on_SerialData_readyToRead);//串口讀取槽函數
void Widget::on_SerialData_readyToRead()
{QString revMessage = serialPort->readAll();qDebug() << "getMessage:"<< revMessage;ui->textEditRev->append(revMessage);//將接收的信息記錄在文本上
}
2.2、定時器-QTimer
定時器和單片機中的定時器使用都是類似的,使用起來并不難,QT配合手冊可以更靈活使用:
.h文件class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();void on_checkBox_clicked();void on_checkBox_clicked(bool checked);private:Ui::Widget *ui;QTimer *timer;//定時器變量聲明
};.c文件Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);timer = new QTimer(this);//為定時器創建一個空間connect(timer,&QTimer::timeout,[=](){//定時器信號與槽綁定qDebug() << "timer out!";//時間到了干什么});
}Widget::~Widget()
{delete ui;
}//按鍵按下定時器開始
void Widget::on_pushButton_clicked()
{timer->start(1000);
}
//按鍵按下定時器結束
void Widget::on_pushButton_2_clicked()
{timer->stop();
}
運行結果:
更多使用放方法可以查看手冊:?
2.3、常用屬性類型轉換(會更新)
QString String_data = "hello";//QString轉const char*const char* char_data = String_data.toStdString().c_str();const char* char_data2 = String_data.toLocal8Bit().constData();//QString轉int,其他整數類型也是使用類似函數轉換String_data.toInt();//QString轉Hex顯示QByteArray qtmp = String_data.toUtf8(); //QString轉QByteArrayqtmp = qtmp.toHex(); //QString轉HEXString_data = QString::fromUtf8(qtmp); //QByteArray轉QStringqDebug() << String_data;//HEX顯示轉QStringQString temp = String_data;QByteArray temp2 = String_data.toUtf8(); //QString轉QByteArray轉QStringQByteArray temp3 = QByteArray::fromHex(temp2);//由HEX返回原來本質String_data = QString::fromUtf8(temp3); //QByteArray轉QStringqDebug() << String_data;
運行結果:
2.4、子控件組規則命名優化
在QT工作開發中我們難免會使用相同的子控件來執行大差不差的工作,比如實現一個小項目串口助手中這種情況,很多數量的按鍵都是實現相同的功能-發送
如果作為一個小白來說,我們肯定會使用大量的信號與槽來實現,一個按鍵對應一對信號與槽,這樣就顯的代碼太過于臃腫了,為了簡潔,可以使用通過給子控件規則命名配合事件的使用來簡單化代碼:?
1.我們首先需要給子控件規則命名:
2.然后
注意:頭文件中需要聲明槽函數.c文件
QList<QPushButton *> buttons;
for(int i = 1; i <= 9; i++){QString btnName = QString("pushButton_%1").arg(i);//建立命名QPushButton* btn = findChild<QPushButton *>(btnName);//尋找子控件中QPushButton類中是否有btnNameif(btn){//如果有btn->setProperty("buttonId",i);//設置它的屬性IDbuttons.append(btn);//統一綁定一個槽,然后在這個槽on_command_button_clicked里面進行處理connect(btn,SIGNAL(clicked()),this,SLOT(on_command_button_clicked()));}
}//槽處理
void Widget::on_command_button_clicked()
{QPushButton *btn = qobject_cast<QPushButton *>(sender());//查看誰是發送信號的按鍵if(btn){int num = btn->property("buttonId").toInt();//將它的屬性ID轉換出來QString lineEditName = QString("lineEdit_%1").arg(num);//根據ID找對應的橫線文本QLineEdit *lineEdit = findChild<QLineEdit *>(lineEditName);if(lineEdit)ui->lineEditSendContext->setText(lineEdit->text());QString checkBoxName = QString("checkBox_%1").arg(num);//根據ID找對應的CheckboxQCheckBox *checkBox = findChild<QCheckBox *>(checkBoxName);if(checkBox)ui->checkBHexSend->setChecked(checkBox->isChecked());on_btnSendContext_clicked();//發送信息}
}