目錄Qt 學習筆記全系列傳送門:
Qt 學習筆記 - 第一章 - 快速開始、信號與槽
Qt 學習筆記 - 第二章 - 添加圖片、布局、界面切換
【本章】Qt 學習筆記 - 第三章 - Qt的三駕馬車之一 - 串口編程 + 程式打包成Windows軟體
- 1、創建專案
- 2、UI
- 3、邏輯功能
- 4、程式打包和部署
1、創建專案
實作串口助手
-
創建 Qt Widgets Application 專案 seial
-
基類選擇 Widget
2、UI
-
UI設計
- 接收框組件,在分類 Input Widgets 中,Plain Text Edit 組件(QPlainTextEdit),雙擊可以編輯選項,置頂項為默認選擇屬性,勾選組件的只讀屬性 readOnly
- 屬性選擇,在分類 Input Widgets 中,Combo Box 組件(QComboBox)
- 發送框,在分類在 Input Widgets 中,Line Edit 組件(QLineEdit)
- 資訊框,寫個廣告之類的可以使用,在分類 中,Group Box 組件(QGroupBox)
- 控制元件改名
-
UI代碼展示
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Widget</class> <widget name="Widget"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>480</height> </rect> </property> <property name="windowTitle"> <string>Widget</string> </property> <widget name="layoutWidget"> <property name="geometry"> <rect> <x>31</x> <y>31</y> <width>737</width> <height>385</height> </rect> </property> <layout name="gridLayout_3"> <item row="0" column="0"> <widget name="recvEdit"> <property name="readOnly"> <bool>true</bool> </property> </widget> </item> <item row="1" column="0"> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>40</height> </size> </property> </spacer> </item> <item row="2" column="0"> <layout name="gridLayout_2"> <item row="0" column="0"> <layout name="gridLayout"> <item row="0" column="0"> <widget name="label_2"> <property name="text"> <string>波特率</string> </property> </widget> </item> <item row="0" column="1"> <widget name="baundrateCb"> <item> <property name="text"> <string>4800</string> </property> </item> <item> <property name="text"> <string>9600</string> </property> </item> <item> <property name="text"> <string>115200</string> </property> </item> </widget> </item> <item row="1" column="0"> <widget name="label"> <property name="text"> <string>串口號</string> </property> </widget> </item> <item row="1" column="1"> <widget name="serialCb"/> </item> <item row="2" column="0"> <widget name="label_5"> <property name="text"> <string>資料位</string> </property> </widget> </item> <item row="2" column="1"> <widget name="dataCb"> <item> <property name="text"> <string>5</string> </property> </item> <item> <property name="text"> <string>6</string> </property> </item> <item> <property name="text"> <string>7</string> </property> </item> <item> <property name="text"> <string>8</string> </property> </item> </widget> </item> <item row="3" column="0"> <widget name="label_4"> <property name="text"> <string>停止位</string> </property> </widget> </item> <item row="3" column="1"> <widget name="stopCb"> <item> <property name="text"> <string>1</string> </property> </item> <item> <property name="text"> <string>1.5</string> </property> </item> <item> <property name="text"> <string>2</string> </property> </item> </widget> </item> <item row="4" column="0"> <widget name="label_3"> <property name="text"> <string>校驗位</string> </property> </widget> </item> <item row="4" column="1"> <widget name="checkCb"> <item> <property name="text"> <string>none</string> </property> </item> </widget> </item> </layout> </item> <item row="0" column="1"> <spacer name="horizontalSpacer_4"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item row="0" column="2"> <layout name="verticalLayout_2"> <item> <widget name="groupBox"> <property name="title"> <string>歡迎使用,這是一個資訊框</string> </property> <widget name="label_6"> <property name="geometry"> <rect> <x>120</x> <y>30</y> <width>161</width> <height>21</height> </rect> </property> <property name="text"> <string>demo info...</string> </property> </widget> </widget> </item> <item> <widget name="sendEdit"/> </item> <item> <layout name="horizontalLayout_6"> <item> <widget name="openBt"> <property name="text"> <string>打開串口</string> </property> </widget> </item> <item> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item> <widget name="closeBt"> <property name="text"> <string>關閉串口</string> </property> </widget> </item> <item> <spacer name="horizontalSpacer_2"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item> <widget name="sendBt"> <property name="text"> <string>發送</string> </property> </widget> </item> <item> <spacer name="horizontalSpacer_3"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item> <widget name="clearBt"> <property name="text"> <string>清空</string> </property> </widget> </item> </layout> </item> </layout> </item> </layout> </item> </layout> </widget> </widget> <layoutdefault spacing="6" margin="11"/> <resources/> <connections/> </ui>
3、邏輯功能
-
在工程檔案中引入
serialportQT += core gui serialport -
獲取串口資訊并展示到頁面上,在目前 UI 對應的 cpp 的構造中進行
說明:需要連接單片機才能顯示串口號
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); QStringList serialNamePorts; // QSerialPort 是串口資訊類,用于存放串口資訊 // QSerialPortInfo::availablePorts() 自動搜索可用串口,回傳串口資訊類物件的陣列 foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { // 將得到的串口資訊的串口號加入到 QStringList 中 serialNamePorts<<info.portName(); } // 將可用串口的串列顯示到頁面的下拉框中 ui->serialCb->addItems(serialNamePorts); } -
其他控制元件的邏輯功能
-
點擊打開串口時對串口進行初始化
-
對串口的宣告和創建
-
頭檔案
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QSerialPort> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); // 宣告QSerialPort *serialPort QSerialPort *serialPort; private slots: void on_openBt_clicked(); void on_closeBt_clicked(); void on_sendBt_clicked(); void on_clearBt_clicked(); private: Ui::Widget *ui; }; #endif // WIDGET_H -
Cpp檔案
#include "widget.h" #include "ui_widget.h" #include <QSerialPortInfo> #include <QMessageBox> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // ... serialPort = new QSerialPort(this); // ... } Widget::~Widget() { delete serialPort; delete ui; }
-
-
打開按鈕單擊信號的槽函式
// 點擊打開串口時將資料設定進串口并打開串口 void Widget::on_openBt_clicked() { QSerialPort::BaudRate baudReat; QSerialPort::DataBits dataBits; QSerialPort::StopBits stopBits; QSerialPort::Parity checkBits; // 獲取界面上的值 switch(ui->baundrateCb->currentText().toInt()) { case QSerialPort::Baud4800: baudReat = QSerialPort::Baud4800; break; case QSerialPort::Baud9600: baudReat = QSerialPort::Baud9600; break; case QSerialPort::Baud115200: baudReat = QSerialPort::Baud115200; break; } switch(ui->dataCb->currentText().toInt()) { case QSerialPort::Data5: dataBits = QSerialPort::Data5; break; case QSerialPort::Data6: dataBits = QSerialPort::Data6; break; case QSerialPort::Data7: dataBits = QSerialPort::Data7; break; case QSerialPort::Data8: dataBits = QSerialPort::Data8; break; } int stopTmp = ui->stopCb->currentText().toInt(); if (stopTmp == QSerialPort::OneStop) { stopBits = QSerialPort::OneStop; } else if (stopTmp == QSerialPort::OneAndHalfStop) { stopBits = QSerialPort::OneAndHalfStop; } else if (stopTmp == QSerialPort::TwoStop) { stopBits = QSerialPort::TwoStop; } if (ui->checkCb->currentText() == "none") { checkBits = QSerialPort::NoParity; } // 使用獲取到的資料設定串口 serialPort->setPortName(ui->serialCb->currentText()); serialPort->setBaudRate(baudReat); serialPort->setDataBits(dataBits); serialPort->setStopBits(stopBits); serialPort->setParity(checkBits); // 打開串口,需要先判斷串口是否打開成功 if (serialPort->open(QIODevice::ReadWrite) == true) { QMessageBox::information(this, "提示", "success!"); } else { QMessageBox::critical(this, "提示", "failed!"); } } -
關閉按鈕單擊信號槽函式
void Widget::on_closeBt_clicked() { serialPort->close(); } -
發送按鈕單擊信號槽函式
void Widget::on_sendBt_clicked() { // 將UI發送的QString轉換為char* 型別,寫入到serialPort serialPort->write(ui->sendEdit->text().toLocal8Bit().data()); } -
串口有東西可讀時,在接收框中進行展示
-
定義槽函式,在頭檔案中
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QSerialPort> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT // ... private slots: // ... // 定義串口有東西可讀時觸發的槽函式 void serialPortReadyRead_Slot(); // ... }; #endif // WIDGET_H -
手動系結可讀信號與槽函式,在構造中
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); QStringList serialNamePorts; serialPort = new QSerialPort(this); // 手動關聯讀信號與自定義槽函式serialPortReadyRead_Slot(),串口有東西可讀時觸發槽函式 connect(serialPort, SIGNAL(readyRead()), this, SLOT(serialPortReadyRead_Slot())); // ... } -
實作槽函式
// 串口有東西可讀時產生信號,觸發槽函式 void Widget::serialPortReadyRead_Slot() { // 接收UI中輸入框的資料 QString buffer = QString(serialPort->readAll()); // 將接收到的資料顯示到UI的recvEdit中 ui->recvEdit->appendPlainText(buffer); }
-
-
清除按鈕單擊信號槽函式
void Widget::on_clearBt_clicked() { ui->recvEdit->clear(); }
-
-
4、程式打包和部署
-
切換到 Release 模式進行編譯
由于缺少動態庫,打包好的程式暫時還無法運行
-
匯出檔案位置:位于專案目錄所在路徑下,檔案名以 Release 結尾,如:
build-seial-Desktop_Qt_5_11_1_MinGW_32bit-Release -
圖示:

-
-
為打包好的程式更換圖示
需要使用
.ico格式的圖片-
將圖示拷貝到工程目錄下
-
在工程檔案中添加如下代碼,再重新編譯即可
RC_ICONS = serial_icon.ico
-
-
封包操作,需要用到 Qt 的控制臺
-
創建一個新的目錄,用于存放封包好的檔案,不能包含中文路徑
-
將打包好的
.exe檔案拷貝到新的目錄下 -
從控制臺進入新目錄中
cd /d C:\xxx\xxxD:\Tools\Qt\Qt5.11.1\5.11.1\mingw53_32>cd /d C:\Users\Dandelion\Desktop\SerialTools C:\Users\Dandelion\Desktop\SerialTools>dir 驅動器 C 中的卷是 OS 卷的序列號是 EAE6-1E0A C:\Users\Dandelion\Desktop\SerialTools 的目錄 2023/03/10 02:22 <DIR> . 2023/03/10 02:20 <DIR> .. 2023/03/10 02:17 48,640 seial.exe 1 個檔案 48,640 位元組 2 個目錄 63,272,501,248 可用位元組 C:\Users\Dandelion\Desktop\SerialTools> -
使用
windeployqt工具將動態庫加到當前目錄下:windeployqt seial.exeC:\Users\Dandelion\Desktop\SerialTools>windeployqt seial.exe C:\Users\Dandelion\Desktop\SerialTools\seial.exe 32 bit, release executable Adding Qt5Svg for qsvgicon.dll Skipping plugin qtvirtualkeyboardplugin.dll due to disabled dependencies (Qt5Qml Qt5Quick). Direct dependencies: Qt5Core Qt5Gui Qt5SerialPort Qt5Widgets All dependencies : Qt5Core Qt5Gui Qt5SerialPort Qt5Widgets To be deployed : Qt5Core Qt5Gui Qt5SerialPort Qt5Svg Qt5Widgets Updating Qt5Core.dll. Updating Qt5Gui.dll. Updating Qt5SerialPort.dll. Updating Qt5Svg.dll. Updating Qt5Widgets.dll. Updating libGLESV2.dll. Updating libEGL.dll. Updating D3Dcompiler_47.dll. Updating opengl32sw.dll. Updating libgcc_s_dw2-1.dll. Updating libstdc++-6.dll. Updating libwinpthread-1.dll. Patching Qt5Core.dll... Creating directory C:/Users/Dandelion/Desktop/SerialTools/iconengines. Updating qsvgicon.dll. Creating directory C:/Users/Dandelion/Desktop/SerialTools/imageformats. Updating qgif.dll. Updating qicns.dll. Updating qico.dll. Updating qjpeg.dll. Updating qsvg.dll. Updating qtga.dll. Updating qtiff.dll. Updating qwbmp.dll. Updating qwebp.dll. Creating directory C:/Users/Dandelion/Desktop/SerialTools/platforms. Updating qwindows.dll. Creating directory C:/Users/Dandelion/Desktop/SerialTools/styles. Updating qwindowsvistastyle.dll. Creating C:\Users\Dandelion\Desktop\SerialTools\translations... Creating qt_ar.qm... Creating qt_bg.qm... Creating qt_ca.qm... Creating qt_cs.qm... Creating qt_da.qm... Creating qt_de.qm... Creating qt_en.qm... Creating qt_es.qm... Creating qt_fi.qm... Creating qt_fr.qm... Creating qt_gd.qm... Creating qt_he.qm... Creating qt_hu.qm... Creating qt_it.qm... Creating qt_ja.qm... Creating qt_ko.qm... Creating qt_lv.qm... Creating qt_pl.qm... Creating qt_ru.qm... Creating qt_sk.qm... Creating qt_uk.qm... C:\Users\Dandelion\Desktop\SerialTools>
-
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/546326.html
標籤:其他
上一篇:Python基礎_概述
