QT上位机开发

QT上位机开发本文只介绍 Windows 的 QT 上位机开发 以串口为例 QT 版本为 5 15

大家好,欢迎来到IT知识分享网。


前言

  本文只介绍Windows的QT上位机开发,以串口为例。本文的QT版本为5.15。

  • C++基础见链接:QT上位机开发

一、环境搭建

1.1 IDE下载

  • Qt官方下载地址:https://www.qt.io/download#eval-form-modal
    在这里插入图片描述
    注意:这里下载的在线安装器,必须先下载然后根据提示注册,才能称为开源用户,否则为商业用户。

  也可以使用国内服务器平台下载:

  • 中国科学技术大学:http://mirrors.ustc.edu.cn/qtproject/
  • 清华大学:https://mirrors.tuna.tsinghua.edu.cn/qt/

1.2 添加环境变量

二、Qt Creator的使用

2.1 快捷键

快捷键 作用
Ctrl + Space 代码自动完成
Ctrl + I 格式化文本
F2 跳转到下一个错误或警告
Shift + F2 跳转到上一个错误或警告
Ctrl + / 注释或取消注释所选行
Ctrl + K 跳转到定义
Ctrl + E 打开最近的文件
Ctrl + Shift + E 打开最近的项目
Ctrl + F12 显示当前文件的类或函数列表
F4 跳转到包含光标所在文本的定义
Ctrl + Shift + F4 返回上一个查看的位置
Ctrl + R 构建项目。
Ctrl + B 构建并运行项目。
Ctrl + D 调试项目。
Ctrl + Shift + B 构建所有项目。
Ctrl + T 运行单元测试。
F5 重新运行应用程序。
F1 帮助文档

2.2 创建QT项目

  • QMainWindow:主窗口类,主窗口具有主菜单栏、工具栏和状态栏
  • QWidget:是可视界面类的基类,也就是说QMainWindow类也是由QWidget继承封装而来。一般嵌入式里用
  • QDialog:对话框类,建立一个对话框界面
  • 项目文件.pro:是项目管理文件,当加入了文件或者删除了文件,Qt Creator 会自动修改这个文件
  • Header头文件分组:存放的是项目内所有的头文件*.h
  • Source源文件分组:这个节点下存放的是项目内的所有 C++源码文件*.cpp。main是主函数,mainwindow.cpp是窗口界面对应的类的源文件
  • Forms界面文件分组:这个节点下是存放项目内所有界面文件.ui。.ui文件由XML语言描述组成,编译时会生成相应的cpp文件,一般情况下不需要在xml格式下对这个文件进行编辑

  双击mainwindow.ui,进入“Ui 设计器”页面,拖动Label控件,就可以输入简单文本,这里我们已经完成显示“Hello World!”的设计了。
在这里插入图片描述
  回到编辑界面,点击编译,就可以生成一个简单UI
在这里插入图片描述


2.3 帮助文档使用

  这边以QPushButton为例,在帮助里搜索对应的类
在这里插入图片描述
  可以查看PropertiesPublic Functions这个标题下的属性和函数,点击Inherits可以查看父类的信息
在这里插入图片描述
  最后可以使用快捷键Alt + ←返回到上一级,或者Alt + →进入下一级



三、Qt信号与槽

  • 信号(Signal):就是在特定情况下被发射的事件,例如 PushButton 最常见的信号就是鼠标单击时发射的 clicked() 信号,简而言之就是输入激励
  • 槽(Slot):就是对信号响应的函数,职责就是对Qt框架中产生的信号进行处理

3.1 标准信号与槽的使用

  标准信号与槽就是指QT自带信号与槽,例如PushButton最常见的信号就是鼠标单击时发射的 clicked() 信号。信号与槽关联是用QObject::connect()函数实现的,connect()是QObject类的一个静态函数,而QObject是所有Qt类的基类,通过帮助可以查看函数使用
在这里插入图片描述
  功能简单只需要修改main.cpp文件

#include <QApplication> #include <QPushButton> #include <QLineEdit> #include <QDebug> int main(int argc, char *argv[]) { 
     QApplication a(argc, argv); //点击按钮 QPushButton *button = new QPushButton("Click Me"); QObject::connect(button, &QPushButton::clicked, [=]() { 
     qInfo() << "Button Clicked!"; }); button->show(); return a.exec(); } 

3.2 自定义信号与槽

  自定义信号可以更好的对控件进行统一管理

  1. 创建信号与槽
      新建一个不带ui的项目(取消勾选ui),主函数文件main.cpp可以不动,在mainwindow.h头文件里添加函数声明,有以下注意点:
  • 在使用信号与槽的类中,必须在类的定义中加入宏Q_OBJECT
  • 信号需要使用signals关键字进行声明
  • 声明的槽函数必须是无返回值类型 void,和无需参数
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QPushButton> class MainWindow : public QMainWindow { 
     Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); signals: /* 声明一个信号,只需声明,无需定义 */ void pushButtonTextChanged(); public slots: /* 声明一个槽函数 */ void changeButtonText(); /* 声明按钮点击的槽函数 */ void pushButtonClicked(); private: /* 声明一个对象pushButton */ QPushButton *pushButton; }; #endif // MAINWINDOW_H 
  1. 信号与槽的实现
      在mianwindow.cpp里实现槽函数的定义,有以下注意点:
  • 使用connect()连接信号与槽,connect()是QObject类的一个静态函数,而QObject是所有Qt类的基类,在实际调用时可以忽略前面的限定符
  • 习惯性在信号函数前加关键字: emit表示显示的声明一下信号要被发射了,可以省略不写,没有特殊含义
  • 因为我们pushButtonClicked()是本类里定义的槽,所以用this来接收
#include "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { 
     /* 设置窗体的宽为800,高为480 */ this->resize(800,480); /* 实例化pushButton对象 */ pushButton = new QPushButton(this); /* 调用setText()方法设定按钮的文本 */ pushButton->setText("我是一个按钮"); /* 信号与槽连接 */ connect(pushButton, SIGNAL(clicked()), this, SLOT(pushButtonClicked())); connect(this, SIGNAL(pushButtonTextChanged()), this, SLOT(changeButtonText())); } MainWindow::~MainWindow() { 
    } /* 实现按钮点击槽函数 */ void MainWindow::pushButtonClicked() { 
     /* 使用emit发送信号 */ emit pushButtonTextChanged(); } /* 实现按钮文本改变的槽函数 */ void MainWindow::changeButtonText() { 
     /* 在槽函数里改变按钮的文本 */ pushButton->setText("被点击了!"); } 

四、Qt控件

4.1 QMainWindow

  QMainWindow提供了用于构建应用程序用户界面的框架:

  • 菜单栏(Menu Bar)QMenuBar对象用于创建菜单栏,菜单栏通常包含一个或多个菜单,每个菜单包含若干个菜单项。
  • 工具栏(Tool Bar)QToolBar对象用于创建工具栏,工具栏通常包含一组快捷操作按钮,用于执行常用的功能。
  • 状态栏(Status Bar)QStatusBar对象用于创建状态栏,用于显示应用程序的状态信息、提示信息等。
  • 中央部件(Central Widget): 通常是一个自定义的QWidget派生类,作为主窗口的中央区域,用于放置应用程序的主要内容。centralWidget支持支持文档-视图架构,可以通过多文档界面(MDI)或单文档界面(SDI)的方式管理多个文档。
  • Dock窗口(Dock Widgets)QDockWidget对象用于创建可停靠的面板,用户可以拖动和停靠这些面板。

在这里插入图片描述

  1. 创建菜单栏
      首先在最上方添加菜单项,然后新建菜单列表
    在这里插入图片描述
      将菜单列表托上去就可以添加,直接添加只能添加英文
    在这里插入图片描述



  2. 创建工具栏
      右击添加工具栏,然后可以使用同样的方式直接拖动
    在这里插入图片描述

  3. 状态栏
      状态栏是一个用于显示应用程序状态信息、提示信息和用户交互的底部区域。状态栏通常用于向用户提供反馈、进度信息或一般性的应用程序状态,可以使用statusBar()函数来获取当前的状态栏对象
QLabel *statusLabel = new QLabel("Status Label", this); statusBar()->addPermanentWidget(statusLabel); 
  1. 停靠窗口
      拖拽控件到ui里,右侧可以看到相应的对象与类,选中后在右下角属性对其修改
    在这里插入图片描述

4.2 按钮

  首先打开ui设计界面,可以从左侧过滤器里找到Button
在这里插入图片描述

  • QPushButton:下压按钮,继承QAbstractButton类,通常用于执行命令或触发事件,上一小节使用过
  • QToolButton:工具按钮,继承QAbstractButton类。是一种用于命令或者选项的可以快速访问的按钮,通常在ToolBar里面。工具按钮通常显示的是图标,而不是文本标签。ToolButton支持自动浮起。在自动浮起模式中,按钮只有在鼠标指向它的时候才绘制三维的框架。
  • QRadioButton:选择按钮,继承QAbstractButton类。RadioButton 单选按钮(单选框)通常成组出现,用于提供两个或多个互斥选项。
  • QCheckBox:检查框,继承QAbstractButton。复选按钮(复选框)与 RadioButton 的区别是选择模式,单选按钮提供多选一,复选按钮提供多选多。.
  • QCommandLinkButton:命令链接按钮,继承QPushButton。QCommandLinkButton 控件和 RadioButton 相似,都是用于在互斥选项中选择一项。表面上同平面按钮一样,但是 CommandLinkButton 除带有正常的按钮上的文字描述文本外,默认情况下,它也将携带一个箭头图标,表明按下按钮将打开另一个窗口或页面。
  • QDialogButtonBox:对话框按钮,继承QWidget。常用于对话框里自定义按钮,比如“确定”和“取消”按钮。

4.3 容器

在这里插入图片描述

  • Group Box(组框)QGroupBox 继承 QWidget,为构建分组框提供了支持。分组框通常带有一个边框和一个标题栏,作为容器部件来使用,在其中可以布置各种窗口部件。布局时可用作一组控件的容器,但是需要注意的是,内部通常使用布局控件(如 QBoxLayout)进行布局。组框还提供键盘快捷方式,键盘快捷方式将键盘焦点移动到组框的一个子部件。
  • Scroll Area(滚动区域)QScrollArea继承QAbstractScrollArea。滚动区域用于在框架中显示子部件的内容。如果小部件超过框架的大小,视图就会出现滚动条,以便可以查看子小部件的整个区域。
  • Tool Box(工具箱):QToolBox继承QFrame。QToolBox 类提供了一列选项卡小部件项。工具箱是一个小部件,它显示一列选项卡在另一列的上面,当前项显示在当前选项卡的下面。每个选项卡在选项卡列中都有一个索引位置。选项卡的项是 QWidget。
  • Tab Widget(标签小部件)QTabWidget继承 QWidget。abWidget 类提供了一组选项卡(多页面)小部件。QTabWidget主要是用来分页显示的,每一页一个界面,众多界面公用一块区域,节省了界面大小,很方便的为用户显示更多的信息。
  • Stacked WIdget(堆叠小部件)QStackedWidget继承 QFrame。QStackedWidget 类提供了一个小部件堆栈,其中一次只能看到一个小部件,与 的设置面板类似。QStackedWidget 可用于创建类似于 QTabWidget 提供的用户界面。它是构建在 QStackedLayout 类之上的一个方便的布局小部件。
  • Frame(帧)QFrame继承了QWidget的属性, QFrame 类是有框架的窗口部件的基类,它绘制框架并且调用一个虚函数 drawContents()来填充这个框架。 这种类型的容器窗口可以提供边框, 并且可以设置边框的样式、宽度以及边框的阴影
  • Widget(小部件)QWidget类是所有用户界面对象的基类(如 QLabel 类继承于 QFrame 类,而 QFrame 类又继承于 QWidget 类)。
  • MDI Area(MDI 区域)QMdiArea继承QAbstractScrollArea。QMdiArea 小部件提供一个显示 MDI 窗口的区域。QMdiArea的功能本质上类似于MDI窗口的窗口管理器。大多数复杂的程序,都使用MDI框架
  • Dock Widget(停靠窗体部件)QDockWidget继承QWidget。QDockWidget 类提供了一个小部件,可以停靠在 QMainWindow 内,也可以作为桌面的顶级窗口浮动。

4.4 窗口

在这里插入图片描述

  可以看出窗口部件很多,有输入与显示窗口,这边就挑部分介绍

  • Comb Box(组合框)QComboBox继承 QWidget 类,被 QFontComboBox 类继承。通常用于用户显示选项列表的方法,这种方法占用最少的屏幕空间。
  • Label(标签):QLabel提供了一种用于文本或图像显示的小部件
  • Progress Bar(进度条)QProgressBar继承 QWidget。QProgressBar 小部件提供了一个水平或垂直的进度条。进度条用于向用户显示操作的进度,并向他们确认应用程序仍在运行。
  • Line Edit(单行编辑框)QLineEdit继承QWidget。QLineEdit 小部件是一个单行文本编辑器。行编辑允许用户使用一组有用的编辑函数输入和编辑一行纯文本,包括撤消和重做、剪切和粘贴以及拖放。
  • Text Edit(文本编辑框)QTextEdit继承QAbstractScrollArea,被 QTextBrowser 继承。QTextEdit 是一个高级所见即所得查看器/编辑器,支持使用 html 样式的标记进行 rich text 格式化。
  • Spin Box(数字旋转框)QSpinBox继承 QAbstractSpinBox。用于处理整数和离散值(例如:月份名称)而 QDoubleSpinBox 则用于处理浮点值。他们之间的区别就是处理数据的类型不同,其他功能都基本相同。
  • Time Edit(时间编辑框)QTimeEdit继承 QDateTimeEdit。QTimeEdit 用于编辑时间,而 QDateEdit 用于编辑日期。
  • Date/Time Edit(日期时间编辑框)QDateTimeEdit提供了一个用于编辑日期和时间的小部件。QDateTimeEdit 允许用户使用键盘或箭头键编辑日期,以增加或减少日期和时间值。
  • List Widget(清单控件)QListWidget继承 QListView。QListWidget 类提供了一个基于项的列表小部件
  • QTreeWidget(树形列表框)QTreeWidget继承 QTreeView。QTreeWidget 类提供了一个使用预定义树模型的树视图。

4.5 布局管理

  基本布局管理类包括:QBoxLayout、QGridLayout、QFormLayout 和 QStackedLayout。这些类都从 QLayout 继承而来,它们都来源于 QObject(而不是 QWidget)

  • QBoxLayout提供了水平和垂直的布局管理;
  • QFormLayout提供了将输入部件和标签成组排列的布局管理;
  • QGridLayout提供了网格形式的布局管理;
  • QStackedLayout提供了一组布局后的部件,可以对它们进行分布显示。

  Layouts组里面的 4 种布局,如下:
在这里插入图片描述
  效果如下:
在这里插入图片描述


五、SerialPort

  这边新建一个名为SerialPort的工程

5.1 修改.Pro文件

  使用串口,需要在.pro项目文件中添加serialport串口模块的支持

QT += core gui serialport 

在这里插入图片描述

5.2 修改mainwindow.h头文件

  头文件需要包含串口常用的两个类QSerialPortInfoQSerialPort

#include <QSerialPort> #include <QSerialPortInfo> 
  • QSerialPortInfo:提供有关现有串行端口的信息
  • QSerialPort:提供访问串行端口的功能
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QSerialPort> #include <QSerialPortInfo> #include <QPushButton> #include <QTextBrowser> #include <QTextEdit> #include <QVBoxLayout> #include <QLabel> #include <QComboBox> #include <QGridLayout> #include <QMessageBox> #include <QDebug> QT_BEGIN_NAMESPACE namespace Ui { 
     class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { 
     Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: /* 串口对象 */ QSerialPort *serialPort; /* 用作接收数据 */ QTextBrowser *textBrowser; /* 用作发送数据 */ QTextEdit *textEdit; /* 按钮 */ QPushButton *pushButton[2]; /* 下拉选择盒子 */ QComboBox *comboBox[5]; /* 标签 */ QLabel *label[5]; /* 垂直布局 */ QVBoxLayout *vboxLayout; /* 网络布局 */ QGridLayout *gridLayout; /* 主布局 */ QWidget *mainWidget; /* 设置功能区域 */ QWidget *funcWidget; /* 布局初始化 */ void layoutInit(); /* 扫描系统可用串口 */ void scanSerialPort(); /* 波特率项初始化 */ void baudRateItemInit(); /* 数据位项初始化 */ void dataBitsItemInit(); /* 检验位项初始化 */ void parityItemInit(); /* 停止位项初始化 */ void stopBitsItemInit(); private slots: void sendPushButtonClicked(); void openSerialPortPushButtonClicked(); void serialPortReadyRead(); }; #endif // MAINWINDOW_H 

5.3 修改mainwindow.cpp源文件

  QSerialPortInfo使用静态函数生成 QSerialPortInfo 对象的列表。列表中的每个 QSerialPortInfo 对象代表一个串行端口,可以查询该端口的名称,系统位置,描述和制造商。QSerialPortInfo类也可以被用作setPort()方法的输入参数,这些参数限定串口端口号,波特率等。

  对于QSerialPort类,我们可以使用如下方法来设置串口的相关参数。

  • setBaudRate()设置波特率
  • setDataBits()设置数据位
  • setParity()设置校验位
  • setStopBits()设置停止位
  • setFlowControl()设置流控制

  设置端口后,可以使用open()方法以只读 (r/o)、仅写 (w/o) 或可读可写 (r/w) 模式打开它。成功打开后,可以使用close()方法关闭端口并取消 I/O 操作。一旦知道端口已准备好读取或写入,就可以使用read()write()方法。

#include "mainwindow.h" #include <QGuiApplication> #include <QScreen> #include <QRect> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { 
     /* 布局初始化 */ layoutInit(); /* 扫描系统的串口 */ scanSerialPort(); /* 波特率项初始化 */ baudRateItemInit(); /* 数据位项初始化 */ dataBitsItemInit(); /* 检验位项初始化 */ parityItemInit(); /* 停止位项初始化 */ stopBitsItemInit(); } void MainWindow::layoutInit() { 
     /* 获取屏幕的分辨率,Qt官方建议使用这 * 种方法获取屏幕分辨率,防上多屏设备导致对应不上 * 注意,这是获取整个桌面系统的分辨率 */ QList <QScreen *> list_screen = QGuiApplication::screens(); /* 如果是ARM平台, 直接设置大小为屏幕的大小 */ #if __arm__ /* 重设大小 */ this->resize(list_screen.at(0)->geometry().width(), list_screen.at(0)->geometry().height()); #else /* 否则则设置主窗体大小为800x480 */ this->resize(800, 480); #endif /* 初始化 */ serialPort = new QSerialPort(this); textBrowser = new QTextBrowser(); textEdit = new QTextEdit(); vboxLayout = new QVBoxLayout(); funcWidget = new QWidget(); mainWidget = new QWidget(); gridLayout = new QGridLayout(); /* QList链表,字符串类型 */ QList <QString> list1; list1<<"串口号:"<<"波特率:"<<"数据位:"<<"检验位:"<<"停止位:"; for (int i = 0; i < 5; i++) { 
     label[i] = new QLabel(list1[i]); /* 设置最小宽度与高度 */ label[i]->setMinimumSize(80, 30); /* 自动调整label的大小 */ label[i]->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); /* 将label[i]添加至网格的坐标(0, i) */ gridLayout->addWidget(label[i], 0, i); } for (int i = 0; i < 5; i++) { 
     comboBox[i] = new QComboBox(); comboBox[i]->setMinimumSize(80, 30); /* 自动调整label的大小 */ comboBox[i]->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); /* 将comboBox[i]添加至网格的坐标(1, i) */ gridLayout->addWidget(comboBox[i], 1, i); } /* QList链表,字符串类型 */ QList <QString> list2; list2<<"发送"<<"打开串口"; for (int i = 0; i < 2; i++) { 
     pushButton[i] = new QPushButton(list2[i]); pushButton[i]->setMinimumSize(80, 30); /* 自动调整label的大小 */ pushButton[i]->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); /* 将pushButton[0]添加至网格的坐标(i, 5) */ gridLayout->addWidget(pushButton[i], i, 5); } pushButton[0]->setEnabled(false); /* 布局 */ vboxLayout->addWidget(textBrowser); vboxLayout->addWidget(textEdit); funcWidget->setLayout(gridLayout); vboxLayout->addWidget(funcWidget); mainWidget->setLayout(vboxLayout); this->setCentralWidget(mainWidget); /* 占位文本 */ textBrowser->setPlaceholderText("接收到的消息"); textEdit->setText("myQt"); /* 信号槽连接 */ connect(pushButton[0], SIGNAL(clicked()), this, SLOT(sendPushButtonClicked())); connect(pushButton[1], SIGNAL(clicked()), this, SLOT(openSerialPortPushButtonClicked())); connect(serialPort, SIGNAL(readyRead()), this, SLOT(serialPortReadyRead())); } void MainWindow::scanSerialPort() { 
     /* 查找可用串口 */ foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { 
     comboBox[0]->addItem(info.portName()); } } void MainWindow::baudRateItemInit() { 
     /* QList链表,字符串类型 */ QList <QString> list; list<<"1200"<<"2400"<<"4800"<<"9600" <<"19200"<<"38400"<<"57600" <<""<<""<<"" <<""; for (int i = 0; i < 11; i++) { 
     comboBox[1]->addItem(list[i]); } comboBox[1]->setCurrentIndex(7); } void MainWindow::dataBitsItemInit() { 
     /* QList链表,字符串类型 */ QList <QString> list; list<<"5"<<"6"<<"7"<<"8"; for (int i = 0; i < 4; i++) { 
     comboBox[2]->addItem(list[i]); } comboBox[2]->setCurrentIndex(3); } void MainWindow::parityItemInit() { 
     /* QList链表,字符串类型 */ QList <QString> list; list<<"None"<<"Even"<<"Odd"<<"Space"<<"Mark"; for (int i = 0; i < 5; i++) { 
     comboBox[3]->addItem(list[i]); } comboBox[3]->setCurrentIndex(0); } void MainWindow::stopBitsItemInit() { 
     /* QList链表,字符串类型 */ QList <QString> list; list<<"1"<<"2"; for (int i = 0; i < 2; i++) { 
     comboBox[4]->addItem(list[i]); } comboBox[4]->setCurrentIndex(0); } void MainWindow::sendPushButtonClicked() { 
     /* 获取textEdit数据,转换成utf8格式的字节流 */ QByteArray data = textEdit->toPlainText().toUtf8(); serialPort->write(data); } void MainWindow::openSerialPortPushButtonClicked() { 
     if (pushButton[1]->text() == "打开串口") { 
     /* 设置串口名 */ serialPort->setPortName(comboBox[0]->currentText()); /* 设置波特率 */ serialPort->setBaudRate(comboBox[1]->currentText().toInt()); /* 设置数据位数 */ switch (comboBox[2]->currentText().toInt()) { 
     case 5: serialPort->setDataBits(QSerialPort::Data5); break; case 6: serialPort->setDataBits(QSerialPort::Data6); break; case 7: serialPort->setDataBits(QSerialPort::Data7); break; case 8: serialPort->setDataBits(QSerialPort::Data8); break; default: break; } /* 设置奇偶校验 */ switch (comboBox[3]->currentIndex()) { 
     case 0: serialPort->setParity(QSerialPort::NoParity); break; case 1: serialPort->setParity(QSerialPort::EvenParity); break; case 2: serialPort->setParity(QSerialPort::OddParity); break; case 3: serialPort->setParity(QSerialPort::SpaceParity); break; case 4: serialPort->setParity(QSerialPort::MarkParity); break; default: break; } /* 设置停止位 */ switch (comboBox[4]->currentText().toInt()) { 
     case 1: serialPort->setStopBits(QSerialPort::OneStop); break; case 2: serialPort->setStopBits(QSerialPort::TwoStop); break; default: break; } /* 设置流控制 */ serialPort->setFlowControl(QSerialPort::NoFlowControl); if (!serialPort->open(QIODevice::ReadWrite)) QMessageBox::about(NULL, "错误", "串口无法打开!可能串口已经被占用!"); else { 
     for (int i = 0; i < 5; i++) comboBox[i]->setEnabled(false); pushButton[1]->setText("关闭串口"); pushButton[0]->setEnabled(true); } } else { 
     serialPort->close(); for (int i = 0; i < 5; i++) comboBox[i]->setEnabled(true); pushButton[1]->setText("打开串口"); pushButton[0]->setEnabled(false); } } void MainWindow::serialPortReadyRead() { 
     /* 接收缓冲区中读取数据 */ QByteArray buf = serialPort->readAll(); textBrowser->insertPlainText(QString(buf)); } MainWindow::~MainWindow() { 
     } 
  • layoutInit()界面布局初始化设置,根据实际的屏的大小,设置全屏显示。其中我们用到垂直布局和网格布局
  • scanSerialPort()查找系统可用的串口,并添加串口名到 comboBox[0]中。
  • baudRateItemInit()波特率初始化,预设常用的波特率, 作为默认选项。并添加波特率到comboBox[1]中。
  • dataBitsItemInit()数据位项初始化,设置默认数据位为 8。
  • parityItemInit()校验位项初始化,默认无校验位。
  • stopBitsItemInit()停止位项初始化,默认停止位为 1。
  • sendPushButtonClicked()发送数据,点击发送按钮时触发。
  • openSerialPortPushButtonClicked()打开或者关闭串口。以我们设置的项使用 Qt 串口提供的设置串口的方法如 setDataBits(QSerialPort::DataBits)等,按步骤设置完串口需要配置的参数就可以打开或者关闭串口了。
  • serialPortReadyRead()从缓冲区里读出数据,并显示到 textBrowser 里。

5.4 效果

在这里插入图片描述

六、QT程序发布与打包

6.1 添加图标

RC_ICONS = SerialPort.ico 

在这里插入图片描述

6.2 生成Release版程序

  如果要发布程序需要切换为Release版本(Debug为调试版本),编译器会对生成的Release版可执行程序进行优化,生成的可执行程序会更小。
在这里插入图片描述
  在Release里找到SerialPort.exe,双击发现打不开,报错原因是找不到一些相关的动态库
在这里插入图片描述
在这里插入图片描述



6.3 添加动态库

  Qt官方给我们提供了相关的发布工具,这个工具叫做windeployqt.exe,文件目录在安装路径的bin文件夹里,如我这边是C:\Qt\5.15.0\mingw81_32\bin
在这里插入图片描述
  先新建一个文件夹,将SerialPort.exe文件复制进来。如果安装时配好环境变量,可以直接打开CMD或者shell,这边我们选择Powershell
在这里插入图片描述
  在当前目录下执行以下命令进行打包



windeployqt SerialPort.exe 

在这里插入图片描述
  此时再双击SerialPort.exe就可以运行
在这里插入图片描述
注意:环境变量里bin路径配置要与新建Qt工程选择的编译器版本相同,否则无法运行。如一个是64位一个为32位


6.4 Qt程序打包

6.4.1 打包成单文件版

6.4.2 打包成可安装版本

  将应用程序和相关的动态库打包成安装包的工具有很多,拿Inno Setup使用举例,官网:https://jrsoftware.org/isdl.php#stable

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/109993.html

(0)
上一篇 2026-02-03 14:26
下一篇 2026-02-03 15:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信