QT 串口上位机读卡显示
目录
一. QT创建工程
二. 软件更换图标
三. QT打包
一. QT创建工程
文件新建,选择创建一个桌面QT。

重命名RFID,并选择工程保存路径

RFID.pro
QT += core gui serialport
#串行串口greaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = RFID
TEMPLATE = appSOURCES += main.cpp\mainwindow.cppHEADERS += mainwindow.hFORMS += mainwindow.ui
#使用C++11
CONFIG += c++11
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QSerialPort>
#include <QByteArray>
#include <QTimer>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECT // Qt 中的宏,支持信号和槽机制public:// 构造函数,初始化 MainWindow 对象explicit MainWindow(QWidget *parent = nullptr);// 析构函数,用于销毁 MainWindow 对象,防止内存泄漏~MainWindow();private slots:// 当发送按钮被点击时执行的槽函数,用于向串口发送数据void on_sendButton_clicked(); // 读取串口接收到的数据,当串口有数据可读时调用void readData(); // 打开或关闭串口,响应打开按钮的点击事件void on_openButton_clicked(); // 扫描可用的串口端口列表,并在界面中显示void scanAvailablePorts(); private:Ui::MainWindow *ui; // UI 界面类的指针,用于访问 UI 中的控件QSerialPort *serial; // 串口对象的指针,处理与串口相关的通信操作QTimer *scanTimer; // 定时器指针,用于定时扫描可用的串口// 配置串口参数(如波特率、数据位、停止位等)void configureSerialPort(); // 更新状态栏的消息,提示用户当前串口的状态void updateStatusMessage();
};#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSerialPortInfo>
#include <QByteArray>
#include <QDebug>
#include <QString>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow),serial(new QSerialPort(this)),scanTimer(new QTimer(this)) // 初始化定时器
{ui->setupUi(this);// 设置窗口标题 左上角的setWindowTitle("白卡写卡软件");// 扫描可用的串口connect(scanTimer, &QTimer::timeout, this, &MainWindow::scanAvailablePorts);scanTimer->start(1000); // 每秒扫描一次connect(ui->sendButton, &QPushButton::clicked, this, &MainWindow::on_sendButton_clicked);connect(ui->openButton, &QPushButton::clicked, this, &MainWindow::on_openButton_clicked);connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData);// 初次扫描端口scanAvailablePorts();
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::scanAvailablePorts()
{QString currentPortName = ui->portComboBox->currentText();bool currentPortStillAvailable = false;ui->portComboBox->clear();const auto serialPortInfos = QSerialPortInfo::availablePorts();for (const QSerialPortInfo &serialPortInfo : serialPortInfos) {ui->portComboBox->addItem(serialPortInfo.portName());if (serialPortInfo.portName() == currentPortName) {currentPortStillAvailable = true;}}// 如果当前选择的端口仍然可用,则重新选择它if (currentPortStillAvailable) {ui->portComboBox->setCurrentText(currentPortName);} else if (ui->portComboBox->count() > 0) {ui->portComboBox->setCurrentIndex(0);}updateStatusMessage();
}void MainWindow::configureSerialPort()
{if (serial->isOpen()) {serial->close();}QString portName = ui->portComboBox->currentText();serial->setPortName(portName);serial->setBaudRate(QSerialPort::Baud115200); // 设置波特率为 115200serial->setDataBits(QSerialPort::Data8);serial->setParity(QSerialPort::NoParity);serial->setStopBits(QSerialPort::OneStop);serial->setFlowControl(QSerialPort::NoFlowControl);if (serial->open(QIODevice::ReadWrite)) {ui->statusBar->showMessage("串口打开: " + portName);scanTimer->stop(); // 成功打开串口后停止扫描} else {ui->statusBar->showMessage("无法打开串口: " + portName);}
}void MainWindow::on_openButton_clicked()
{configureSerialPort();updateStatusMessage();
}void MainWindow::updateStatusMessage()
{if (serial->isOpen()) {ui->statusBar->showMessage("串口打开: " + ui->portComboBox->currentText());} else {ui->statusBar->showMessage("串口未连接");}
}void MainWindow::on_sendButton_clicked()
{if (!serial->isOpen()) {ui->statusBar->showMessage("串口未连接");return;}// 获取用户输入并转换为字节数组QString inputText = ui->inputLineEdit->text();// 将十进制字符串转换为整数bool ok;int decimalValue = inputText.toInt(&ok);if (!ok) {qDebug() << "Invalid decimal input";return;}// 确保整数值在 0 到 255 之间,因为我们要将其表示为一个字节if (decimalValue < 0 || decimalValue > 255) {qDebug() << "Decimal value out of range (0-255)";return;}// 创建并初始化 QByteArrayQByteArray data(11, 0); // 预先分配 11 个字节并初始化为 0data[0] = static_cast<char>(0x40);data[1] = static_cast<char>(0xA9);data[2] = static_cast<char>(0x00);data[3] = static_cast<char>(0x04);data[4] = static_cast<char>(0x00);data[5] = static_cast<char>(0x00);data[6] = static_cast<char>(0x00);data[7] = static_cast<char>(0x00); // 预留一个位置data[8] = static_cast<char>(0x00);data[9] = static_cast<char>(0x00);data[10] = static_cast<char>(0x0D);// 将整数转换为十六进制字节char hexByte = static_cast<char>(decimalValue);// 将该字节放入 QByteArray 的第八个位置(索引 7)data[7] = hexByte;// 发送数据serial->write(data);
}void MainWindow::readData()
{if (!serial->isOpen()) {ui->statusBar->showMessage("串口未连接");return;}QByteArray receivedData = serial->readAll();// 显示接收到的全部数据(十六进制格式)ui->receivedDataTextEdit->append(receivedData.toHex().toUpper());// 获取第13个字节的数据并显示在特定窗口if (receivedData.size() >= 13) {// 获取第13个字节的数据unsigned char byte13 = static_cast<unsigned char>(receivedData[12]);// 将字节转换为十进制表示int decimalValue = static_cast<int>(byte13);// 将十进制整数转换为字符串QString decimalString = QString::number(decimalValue);// 在特定窗口中显示十进制数据ui->byte13Label->setText(decimalString);}
}
mainwindow.ui

1.选择串口的下拉框(Combo Box) : portComboBox2.打开按钮 : openButton3.写卡号输入框(Line Edit) : inputLineEdit4.写卡按钮 : sendButton5.串口数据窗口(Text Edit) : receivedDataTextEdit6.当前卡号显示 (Label): byte13Label
运行效果:

二. 软件更换图标
在工程目录新建文件夹resources

里面放ico格式的图片
iconfont-阿里巴巴矢量图标库
PNG转ICO - 在线转换图标文件

在 Qt Creator 中,右键单击项目名称并选择"添加新文件" > "Qt" > "Qt Resource File",将资源文件添加到项目中

将资源文件命名为"resources.qrc"

在 Qt Creator 中打开"resources.qrc"文件,右键单击文件并选择"添加前缀"。添加一个名称,例如"/icons"

右键单击新创建的前缀("/icons"),然后选择"添加文件",将步骤 2 中的 `.ico` 文件添加到资源文件中
更新 .pro 文件
在 Qt Creator 中打开项目的 .pro 文件。
RC_ICONS = resources/rfid.ico
三. QT打包
以 Release 方式编译生成 exe 程序:

生成的程序运行正常之后,找到项目的生成目录,比如 项目源码路径:C:\Users\Administrator\Desktop\WR\WR\RFID 。
它的项目生成目录是 C:\Users\Administrator\Desktop\WR\build-RFID-Desktop_Qt_5_4_0_MinGW_32bit-Release 。
进入这个文件夹,在进入它的子文件夹 release 里面,找到 RFID.exe,将这个exe 复制到一个新的单独的文件夹里用于发布,比如存到 C:\Users\Administrator\Desktop\WR\WR\Card 文件夹里面。
然后从开始菜单打开 Qt 命令行,

输入命令:cd C:\Users\Administrator\Desktop\WR\WR\Card
然后使用 windeployqt 工具命令:windeployqt RFID.exe

打包完成

直接可以运行

封包软件
打开Enigma Virtual Box,浏览封包的主程序

点击右下角的“文件选项”按钮,打开“文件选项”窗口,并勾选其中的“压缩文件”,如下图中红框所示。压缩后的单文件会小得多,所以建议勾选。

点击左下角的“增加”按钮,开始增加文件,如下图所示。


确认后

点击确定

执行封包

运行

这时候card路径下生成一个新的exe可以发送,也不会少包
![]()
链接: https://pan.baidu.com/s/1U9RA7MdLsOJZUqYMW3FUjg?pwd=ff5q 提取码: ff5q
相关文章:
QT 串口上位机读卡显示
目录 一. QT创建工程 二. 软件更换图标 三. QT打包 一. QT创建工程 文件新建,选择创建一个桌面QT。 重命名RFID,并选择工程保存路径 RFID.pro QT core gui serialport #串行串口greaterThan(QT_MAJOR_VERSION, 4): QT widgetsTARGET RFID TE…...
Chrome谷歌浏览器登录账号next无反应
文章目录 问题描述 我们的Chrome浏览器在更新之后,会出现登录谷歌账号的时候,当你输入你的谷歌邮箱之后,点击 n e x t next next,也就是下一步的时候,页面没有反应,也就是没有跳转到输入密码的页面。 分析 根据logs里…...
Android相关线程基础
线程基础 进程与线程 进程:可以被看做是程序的实体, 是系统进行资源分配和调度的基本单位. 线程:是操作系统调度的最小单元, 也叫轻量级进程 使用多线程的优点 可以减少程序的响应时间。如果某个操作很耗时, 能够避免陷入长时间的等待, 从而有着更好的交互性. 线程较之进…...
uniapp 如何自定义导航栏并自适应机型
如今的移动设备有各种不同的屏幕形状,如刘海屏、水滴屏等。这些异形屏会影响页面的布局,尤其是导航栏和底部栏的显示。通过获取安全区域信息,可以确保页面内容不会被异形屏的特殊区域遮挡。 在设计页面顶部导航栏时,可以根据 saf…...
Java高级Day43-类加载
117.类加载 静态和动态加载 反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载 静态加载:编译时加载相关的类,如果没有则报错,依赖性太强 动态加载:运行时加载需要的类,如果运行时不用该类…...
【LeetCode 算法笔记】155. 最小栈
目录 问题描述单个栈实现双栈实现不开辟额外空间 问题描述 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。 void push(int val) 将元素val推入堆栈。 void pop()…...
面试题 05.01. 插入
目录 一:题目: 二:代码: 三:结果: 一:题目: 给定两个整型数字 N 与 M,以及表示比特位置的 i 与 j(i < j,且从 0 位开始计算)。…...
稠密向量检索、稀疏向量检索、BM25检索三者对比
在当今的信息检索领域,随着人工智能和自然语言处理技术的发展,稠密向量检索和稀疏向量检索成为了两种主要的研究方向。稠密向量检索依托于高维空间中的向量表示,能够捕捉文档的深层语义信息,而稀疏向量检索则侧重于关键词的匹配&a…...
UEFI学习笔记(六):EDK II 模块:Libraries,DriversApplication
UEFI学习笔记(六):EDK II Modules:Libraries,Application&Drivers 一、模块(Modules)的概念1、Library模块2、Application模块3、Driver模块4、Application和Driver的区别 二、EDK II 实现U…...
详解 Pandas 的透视表函数
Pandas 的透视表函数主要为 pivot() 和 pivot_table(),主要的功能为对 DataFrame 的行和列进行重新组合来重塑数据。 一、pivot 函数 pivot 函数只能对数据进行重塑,不能进行聚合 1. 数据准备 import pandas as pddf1 pd.DataFrame({department_id: […...
基于python+django+vue的农业管理系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于pythondjangovueMySQL的农…...
动态内存管理之malloc,free,calloc和realloc函数
Hello,各位小伙伴们,小编在这里祝福各位中秋佳节快乐呀,今天让我们来学习一下动态内存管理吧! 引言 像我们之前在开辟一段空间的时候你可能会使用整型变量来申请一块空间,或者使用数组来申请一段连续的空间ÿ…...
Android 13 固定systemUI的状态栏为黑底白字,不能被系统应用或者三方应用修改
目录 一.背景 二.思路 三.代码流程 1.colos.xml自定义颜色 2.设置状态栏的背景颜色 3.对View进行操作 ①.对Clock(状态栏左侧的数字时钟)进行操作 ②.对电池(BatteryMeterView)进行操作 4.锁屏状态栏 5.patch汇总 一.背景 客户需求将状态栏固定成黑底白字,并且不能让系…...
【CTF Reverse】XCTF GFSJ1092 easyEZbaby_app Writeup(Android+逆向工程+Java)
easyEZbaby_app 究极简单的安卓逆向 解法 得到一个 apk 安装包。 用 jadx 打开,搜索文本 flag,加载所有。 flag 是 obj obj2,来自用户的用户名和密码。 Override // android.view.View.OnClickListenerpublic void onClick(View view) {St…...
ubuntu 22.04 ~24.04 如何修改登录背景
ubuntu 22.04 ~24.04 如何修改登录背景 背景:由于22.04 登录gdm的变更,之前的修改登录背景的方案已经无法使用。现在给大家分享新的使用方法: 1,下载如下路径的脚本: https://download.csdn.net/download/xdhyqd/89…...
Andrej Karpathy谈AI未来:自动驾驶、Transformer与人机融合
引言 在人工智能领域,Andrej Karpathy 是一个无法忽视的名字。从他早期在 OpenAI 的工作,到后来担任 Tesla 的 AI 主管,他在自动驾驶、深度学习等方面的贡献广为人知。最近,卡帕西做客了著名的播客节目 No Priors,他在…...
Vue使用query传参Boolean类型,刷新之后转换为String问题
做项目时发现第一次进入页面时传参是正常的Boolean类型,刷新之后变成了String,这是浏览器进行的一次强制转换; vue-router 传参,不管是 params 形式还是query形式传参,在页面刷新后,params 和 query 对象中…...
开源模型应用落地-qwen模型小试-调用Qwen2-VL-7B-Instruct-更清晰地看世界(一)
一、前言 学习Qwen2-VL ,为我们打开了一扇通往先进人工智能技术的大门。让我们能够深入了解当今最前沿的视觉语言模型的工作原理和强大能力。这不仅拓宽了我们的知识视野,更让我们站在科技发展的潮头,紧跟时代的步伐。 Qwen2-VL 具有卓越的图像和视频理解能力,以及多语言支…...
国学盛典 致敬先贤 《老子与道德经》纪录片研讨会在北京善品堂国学馆圆满落幕
9月10日,《老子与道德经》纪录片研讨会在北京善品堂国学馆圆满落幕。中国著名表演艺术家、曾饰演央视86版电视剧《西游记》中“孙悟空”的六小龄童先生与两百余人传统文化传播者、践行者、爱好者齐聚一堂,共同交流。本次会议由中国文化促进会福文化工作委…...
sqlgun新闻管理系统
一,打开主页 1.输入框测试回显点 -1union select 1,2,3# 出现回显点2 2.查看数据库表名 -1union select 1,database(),3# 3.查看表名 -1union select 1,2,group_concat(table_name) from information_schema.tables where table_schemasqlgunnews# 4.查看admin中…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...
【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
高考志愿填报管理系统---开发介绍
高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发,采用现代化的Web技术,为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## 📋 系统概述 ### 🎯 系统定…...
