基于python+pyqt5的串口助手

基于python+pyqt5的串口助手

环境: pycharm、python3.8,pyqt5,pyserial。(需要该节的工程文件 请私信,或加VX:Crazzy_M,订阅后直接拿源码)

说明: 通过python3.8、pyqt5和pyserial自制串口助手,可以实现基础ascll码,hex数据的收发以及定时发送,还可以实现接收数据的动态波形显示。

功能展示

在工程应用中串口助手的其他功能因项目而异,因此学会基础功能的搭建,在改进的时候就方便很多。

基于python+pyqt5的串口助手

文章目录

*
1.环境的安装(很重要)

+ 1.1.所需包的安装
+ 1.2. 链接QT
+
* 1.2.1 pycharm如何调用QT设计师
* 1.2.2 pycharm中如何更新QT对应的py代码
2.串口助手代码

+ 2.1 主代码
+ 2.2 链接QT的py代码
3.虚拟环境下生成exe(含图标)

+ 3.1任务栏和exe左上角的图标添加
+ 3.2 虚拟环境下生成EXE
+ 3.3 功能演示

; 1.环境的安装(很重要)

Python3.8和pycharm进行常规安装即可(pycharm需要破解一下)。(如果需要安装包可以私信)

1.1.所需包的安装

所需的包

包说明pyqt5链接QTpyqt5-tools链接QTpyserial串口库matplotlib绘图所需的matlib包pyinstaller生成EXE所需的包py2exe生成exe所需的包(关系到exe任务栏和左上角图标能否正常显示

安装方法(下面三个选一个就可以):

①默认方法(安装比较慢):

pip install  pack    (pack是指上面的包)

②推荐使用清华源:

pip install -i https:

③也可以使用其他源

阿里云: https:

豆瓣:http:

安装好包之后

在Terminal下执行 pip list可以看到安装的包

(有些包是上面总结的包附带的)

基于python+pyqt5的串口助手
还有下面这个包
pyqt5-tools

1.2. 链接QT

首先我们GUI是通过QT搭建的,界面如下所示:

基于python+pyqt5的串口助手

我们通过两个步骤进行python和qt的关联,也就是设置下面两个外部工具进行 QT设计师的打开QT代码的更新

基于python+pyqt5的串口助手

; 1.2.1 pycharm如何调用QT设计师

我们要通过pycharm去调用QT设计师去设计GUI界面,但是在pycharm中如何直接调用QT设计师呢?

前提条件是已经安装上面所述的pyqt5的包。

接下来就配置 QtDesigner 外部工具,用来调用QT界面:

基于python+pyqt5的串口助手


file→settings

基于python+pyqt5的串口助手

Settings→Tools→External Tools(扩展包)

里面的QtDesigner和pyuic5是我已经配置好的,没有配置里面是空白的。

基于python+pyqt5的串口助手
③配置QtDesigner

点击”+”号就会出现以下界面

基于python+pyqt5的串口助手
④开始填写

Name: QtDesigner

Program: 选择designer.exe的目录

(一般来说,在你Python安装目录下的\Lib\site-packages\pyqt5-tools\designer.exe。安装的第三方库一般都在Lib文件夹下site-packages文件夹中。装完PyQt5,和PyQt-tools后,该目录下至少会有这俩个文件夹)。

注意 新版本的python下designer.exe的目录在安装Pyqt5-tools后,designer.exe所在路径是python\Lib\site-packages\qt5_applications\Qt\bin\designer.exe(安装目录下找)

我的路径是:

D:\software\python\Anaconda3\Lib\site-packages\qt5_applications\Qt\bin\designer.exe

基于python+pyqt5的串口助手
Arguments: $FileName$ (复制吧,也可以自己选择insert插入,这样保证已经生成的ui文件直接用designer直接打开)

Working directory: $FileDir$ (路径设置,同样可以直接复制,选完program后会把它当默认路径而不是工程路径,这个参数会让路径转为工程路径)

配置完界面如下:

基于python+pyqt5的串口助手
配置完成

在Tools→External Tools中点击QtDesigner就可以打开QT设计师

基于python+pyqt5的串口助手
基于python+pyqt5的串口助手

1.2.2 pycharm中如何更新QT对应的py代码

Qt设计师中,界面设计完毕后怎么转换为py代码呢?

同样需要配置一个外部工具(Pyuic5):

基于python+pyqt5的串口助手

file→settings
基于python+pyqt5的串口助手

Settings→Tools→External Tools(扩展包)

里面的QtDesigner和pyuic5是我已经配置好的,没有配置里面是空白的。

基于python+pyqt5的串口助手
③配置pyuic5

Name: Pyuic5(其实名字随你,你自己懂就行了)

Program: 这里选的是你Python安装目录,找到python.exe(例如我的是D:\software\python\Anaconda3\python.exe)

Arguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py
Working directory: $FileDir$ (这样保证转换的文件是在你的工程目录下的,否则是其他目录)

配置好的界面如下

基于python+pyqt5的串口助手

配置完成

点击Tools→External Tools→pyuic5就可以将QT设计师中GUI界面转换为py文件

基于python+pyqt5的串口助手

; 2.串口助手代码

2.1 主代码

需要工程文件,私信。

import sys
import serial
import serial.tools.list_ports

from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtCore import QTimer
from ui_demo_1 import Ui_Form

from PyQt5.QtGui import QIcon

from PyQt5.QtWidgets import QFileDialog
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas, NavigationToolbar2QT as NavigationToolbar

from matplotlib.figure import Figure

import images

import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("myappid")

from PyQt5 import QtWidgets

class Pyqt5_Serial(QtWidgets.QWidget, Ui_Form):
    def __init__(self):
        super(Pyqt5_Serial, self).__init__()
        self.setupUi(self)
        self.init()
        self.setWindowTitle("Ucom v1.2")
        self.ser = serial.Serial()
        self.port_check()
        self.setWindowIcon(QIcon(':/Ucom.ico'))

        self.data_num_received = 0
        self.lineEdit.setText(str(self.data_num_received))
        self.data_num_sended = 0
        self.lineEdit_2.setText(str(self.data_num_sended))
        self.ReceNumForClear = 0

        self.tabWidget.setTabText(0, '数据接收')
        self.tabWidget.setTabText(1, '波形显示')

        self.static_canvas = FigureCanvas(Figure())
        layout = QtWidgets.QVBoxLayout(self.groupBox)
        layout.addWidget(self.static_canvas)
        tool_bar = NavigationToolbar(self.static_canvas, self.groupBox)
        layout.addWidget(tool_bar)
        self._static_ax1 = self.static_canvas.figure.subplots(1, 1)

    def init(self):

        self.s1__box_1.clicked.connect(self.port_check)

        self.s1__box_2.currentTextChanged.connect(self.port_imf)

        self.open_button.clicked.connect(self.port_open)

        self.close_button.clicked.connect(self.port_close)

        self.s3__send_button.clicked.connect(self.data_send)

        self.timer_send = QTimer()
        self.timer_send.timeout.connect(self.data_send)
        self.timer_send_cb.stateChanged.connect(self.data_send_timer)

        self.tit = 0
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.data_receive)

        self.s3__clear_button.clicked.connect(self.send_data_clear)

        self.s2__clear_button.clicked.connect(self.receive_data_clear)

        self.s3__openfile_button.clicked.connect(self.openFile)

        self.timer1 = QTimer()

    def port_check(self):

        self.Com_Dict = {}
        port_list = list(serial.tools.list_ports.comports())
        self.s1__box_2.clear()
        for port in port_list:
            self.Com_Dict["%s" % port[0]] = "%s" % port[1]
            self.s1__box_2.addItem(port[0])
        if len(self.Com_Dict) == 0:
            self.state_label.setText(" 无串口")

    def port_imf(self):

        imf_s = self.s1__box_2.currentText()
        if imf_s != "":
            self.state_label.setText(self.Com_Dict[self.s1__box_2.currentText()])

    def port_open(self):
        self.ser.port = self.s1__box_2.currentText()
        self.ser.baudrate = int(self.s1__box_3.currentText())
        self.ser.bytesize = int(self.s1__box_4.currentText())
        self.ser.stopbits = int(self.s1__box_6.currentText())
        self.ser.parity = self.s1__box_5.currentText()
        try:
            self.ser.open()
        except:
            QMessageBox.critical(self, "Port Error", "此串口不能被打开!")
            return None

        self.timer.start(2)

        if self.ser.isOpen():
            self.open_button.setEnabled(False)
            self.close_button.setEnabled(True)
            self.formGroupBox1.setTitle("串口状态(已开启)")

    def port_close(self):
        self.timer.stop()
        self.timer_send.stop()
        self.timer1.stop()
        try:
            self.ser.close()
        except:
            pass
        self.open_button.setEnabled(True)
        self.close_button.setEnabled(False)
        self.lineEdit_3.setEnabled(True)

        self.data_num_received = 0
        self.lineEdit.setText(str(self.data_num_received))
        self.data_num_sended = 0
        self.lineEdit_2.setText(str(self.data_num_sended))
        self.formGroupBox1.setTitle("串口状态(已关闭)")

    def data_send(self):
        if self.ser.isOpen():
            input_s = self.s3__send_text.toPlainText()
            if input_s != "":

                if self.hex_send.isChecked():
                    input_s = input_s.strip()
                    send_list = []
                    while input_s != '':
                        try:
                            num = int(input_s[0:2], 16)
                        except ValueError:
                            QMessageBox.critical(self, 'wrong data', '请输入十六进制数据,以空格分开!')
                            return None
                        input_s = input_s[2:].strip()
                        send_list.append(num)
                    input_s = bytes(send_list)

                else:
                    input_s = (input_s + '\r\n').encode('utf-8')

                num = self.ser.write(input_s)
                self.data_num_sended += num
                self.lineEdit_2.setText(str(self.data_num_sended))
        else:
            pass

    def data_receive(self):
        try:
            num = self.ser.inWaiting()
        except:
            self.port_close()
            return None

        if num > 0:
            data = self.ser.read(num)
            num = len(data)
            self.recevive_num = num

            if self.hex_receive.checkState():
                out_s = ''
                self.display = []
                self.display2 = []
                for i in range(0, len(data)):
                    out_s = out_s + '{:02X}'.format(data[i]) + ' '
                    self.display.append(data[i])
                self.s2__receive_text.insertPlainText(out_s)

                self.timer1.start(100)

                self.i = 0
                self.t = []
                self.s = []

                self.timer1.timeout.connect(self.refresh_plot)

            else:

                self.s2__receive_text.insertPlainText(data.decode('iso-8859-1'))

            self.data_num_received += num
            self.ReceNumForClear += num
            self.lineEdit.setText(str(self.data_num_received))
            if self.SetAutoClear.checkState():
                ValueClearNumSet = int(self.ClearNumSet.text())
                if self.ReceNumForClear >= ValueClearNumSet:
                    self.s2__receive_text.setText("")
                    self.ReceNumForClear = 0
                    self.ReceNumForClear = self.ReceNumForClear

            textCursor = self.s2__receive_text.textCursor()

            textCursor.movePosition(textCursor.End)

            self.s2__receive_text.setTextCursor(textCursor)
        else:
            pass

    def refresh_plot(self):

        if(self.i == self.recevive_num):
            self.timer1.stop()

        else:
            self.t.append(self.i)
            self.display2.append(self.display[self.i])
            self._static_ax1.cla()
            self._static_ax1.plot(self.t, self.display2)
            self.static_canvas.draw()
            self.i += 1

    def data_send_timer(self):
        if self.timer_send_cb.isChecked():
            self.timer_send.start(int(self.lineEdit_3.text()))
            self.lineEdit_3.setEnabled(False)
        else:
            self.timer_send.stop()
            self.lineEdit_3.setEnabled(True)

    def send_data_clear(self):
        self.s3__send_text.setText("")
        self.data_num_sended = 0
        self.lineEdit_2.setText(str(self.data_num_sended))

    def receive_data_clear(self):
        self.data_num_received = 0
        self.lineEdit.setText(str(self.data_num_received))
        self.s2__receive_text.setText("")

    def openFile(self):
        fname = QFileDialog.getOpenFileName(self, '打开文件', './')
        if fname[0]:
            with open(fname[0], 'r', encoding='gb18030', errors='ignore') as f:
                self.s3__send_text.setText(f.read())

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    myshow = Pyqt5_Serial()
    myshow.show()
    sys.exit(app.exec_())

2.2 链接QT的py代码

链接QT的代码(该代码是QT的UI生成的代码,不是敲出来的哈):


from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.setEnabled(True)
        Form.resize(727, 535)
        self.formGroupBox = QtWidgets.QGroupBox(Form)
        self.formGroupBox.setGeometry(QtCore.QRect(20, 20, 167, 301))
        self.formGroupBox.setObjectName("formGroupBox")
        self.formLayout = QtWidgets.QFormLayout(self.formGroupBox)
        self.formLayout.setContentsMargins(10, 10, 10, 10)
        self.formLayout.setSpacing(10)
        self.formLayout.setObjectName("formLayout")
        self.s1__lb_1 = QtWidgets.QLabel(self.formGroupBox)
        self.s1__lb_1.setObjectName("s1__lb_1")
        self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.s1__lb_1)
        self.s1__box_1 = QtWidgets.QPushButton(self.formGroupBox)
        self.s1__box_1.setAutoRepeatInterval(100)
        self.s1__box_1.setDefault(True)
        self.s1__box_1.setObjectName("s1__box_1")
        self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.s1__box_1)
        self.s1__lb_2 = QtWidgets.QLabel(self.formGroupBox)
        self.s1__lb_2.setObjectName("s1__lb_2")
        self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.s1__lb_2)
        self.s1__box_2 = QtWidgets.QComboBox(self.formGroupBox)
        self.s1__box_2.setObjectName("s1__box_2")
        self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.s1__box_2)
        self.s1__lb_3 = QtWidgets.QLabel(self.formGroupBox)
        self.s1__lb_3.setObjectName("s1__lb_3")
        self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.s1__lb_3)
        self.s1__box_3 = QtWidgets.QComboBox(self.formGroupBox)
        self.s1__box_3.setObjectName("s1__box_3")
        self.s1__box_3.addItem("")
        self.s1__box_3.addItem("")
        self.s1__box_3.addItem("")
        self.s1__box_3.addItem("")
        self.s1__box_3.addItem("")
        self.s1__box_3.addItem("")
        self.s1__box_3.addItem("")
        self.s1__box_3.addItem("")
        self.s1__box_3.addItem("")
        self.s1__box_3.addItem("")
        self.s1__box_3.addItem("")
        self.s1__box_3.addItem("")
        self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.s1__box_3)
        self.s1__lb_4 = QtWidgets.QLabel(self.formGroupBox)
        self.s1__lb_4.setObjectName("s1__lb_4")
        self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.s1__lb_4)
        self.s1__box_4 = QtWidgets.QComboBox(self.formGroupBox)
        self.s1__box_4.setObjectName("s1__box_4")
        self.s1__box_4.addItem("")
        self.s1__box_4.addItem("")
        self.s1__box_4.addItem("")
        self.s1__box_4.addItem("")
        self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.s1__box_4)
        self.s1__lb_5 = QtWidgets.QLabel(self.formGroupBox)
        self.s1__lb_5.setObjectName("s1__lb_5")
        self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.s1__lb_5)
        self.s1__box_5 = QtWidgets.QComboBox(self.formGroupBox)
        self.s1__box_5.setObjectName("s1__box_5")
        self.s1__box_5.addItem("")
        self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.s1__box_5)
        self.open_button = QtWidgets.QPushButton(self.formGroupBox)
        self.open_button.setObjectName("open_button")
        self.formLayout.setWidget(7, QtWidgets.QFormLayout.SpanningRole, self.open_button)
        self.close_button = QtWidgets.QPushButton(self.formGroupBox)
        self.close_button.setObjectName("close_button")
        self.formLayout.setWidget(8, QtWidgets.QFormLayout.SpanningRole, self.close_button)
        self.s1__lb_6 = QtWidgets.QLabel(self.formGroupBox)
        self.s1__lb_6.setObjectName("s1__lb_6")
        self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.s1__lb_6)
        self.s1__box_6 = QtWidgets.QComboBox(self.formGroupBox)
        self.s1__box_6.setObjectName("s1__box_6")
        self.s1__box_6.addItem("")
        self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.s1__box_6)
        self.state_label = QtWidgets.QLabel(self.formGroupBox)
        self.state_label.setText("")
        self.state_label.setTextFormat(QtCore.Qt.AutoText)
        self.state_label.setScaledContents(True)
        self.state_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.state_label.setObjectName("state_label")
        self.formLayout.setWidget(2, QtWidgets.QFormLayout.SpanningRole, self.state_label)
        self.verticalGroupBox = QtWidgets.QGroupBox(Form)
        self.verticalGroupBox.setGeometry(QtCore.QRect(210, 20, 401, 321))
        self.verticalGroupBox.setObjectName("verticalGroupBox")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalGroupBox)
        self.verticalLayout.setContentsMargins(10, 10, 10, 10)
        self.verticalLayout.setObjectName("verticalLayout")
        self.tabWidget = QtWidgets.QTabWidget(self.verticalGroupBox)
        self.tabWidget.setObjectName("tabWidget")
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName("tab")
        self.s2__receive_text = QtWidgets.QTextBrowser(self.tab)
        self.s2__receive_text.setGeometry(QtCore.QRect(0, 0, 371, 261))
        self.s2__receive_text.setObjectName("s2__receive_text")
        self.tabWidget.addTab(self.tab, "")
        self.tab2 = QtWidgets.QWidget()
        self.tab2.setObjectName("tab2")
        self.groupBox = QtWidgets.QGroupBox(self.tab2)
        self.groupBox.setGeometry(QtCore.QRect(0, 0, 371, 261))
        self.groupBox.setTitle("")
        self.groupBox.setObjectName("groupBox")
        self.tabWidget.addTab(self.tab2, "")
        self.verticalLayout.addWidget(self.tabWidget)
        self.verticalGroupBox_2 = QtWidgets.QGroupBox(Form)
        self.verticalGroupBox_2.setGeometry(QtCore.QRect(210, 350, 401, 141))
        self.verticalGroupBox_2.setObjectName("verticalGroupBox_2")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalGroupBox_2)
        self.verticalLayout_2.setContentsMargins(10, 10, 10, 10)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.s3__send_text = QtWidgets.QTextEdit(self.verticalGroupBox_2)
        self.s3__send_text.setObjectName("s3__send_text")
        self.verticalLayout_2.addWidget(self.s3__send_text)
        self.s3__send_button = QtWidgets.QPushButton(Form)
        self.s3__send_button.setGeometry(QtCore.QRect(620, 450, 61, 31))
        self.s3__send_button.setObjectName("s3__send_button")
        self.s3__clear_button = QtWidgets.QPushButton(Form)
        self.s3__clear_button.setGeometry(QtCore.QRect(620, 370, 61, 31))
        self.s3__clear_button.setObjectName("s3__clear_button")
        self.formGroupBox1 = QtWidgets.QGroupBox(Form)
        self.formGroupBox1.setGeometry(QtCore.QRect(20, 390, 171, 101))
        self.formGroupBox1.setObjectName("formGroupBox1")
        self.formLayout_2 = QtWidgets.QFormLayout(self.formGroupBox1)
        self.formLayout_2.setContentsMargins(10, 10, 10, 10)
        self.formLayout_2.setSpacing(10)
        self.formLayout_2.setObjectName("formLayout_2")
        self.label = QtWidgets.QLabel(self.formGroupBox1)
        self.label.setObjectName("label")
        self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label)
        self.label_2 = QtWidgets.QLabel(self.formGroupBox1)
        self.label_2.setObjectName("label_2")
        self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_2)
        self.lineEdit = QtWidgets.QLineEdit(self.formGroupBox1)
        self.lineEdit.setObjectName("lineEdit")
        self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.lineEdit)
        self.lineEdit_2 = QtWidgets.QLineEdit(self.formGroupBox1)
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.lineEdit_2)
        self.hex_send = QtWidgets.QCheckBox(Form)
        self.hex_send.setGeometry(QtCore.QRect(620, 350, 71, 16))
        self.hex_send.setChecked(False)
        self.hex_send.setObjectName("hex_send")
        self.hex_receive = QtWidgets.QCheckBox(Form)
        self.hex_receive.setEnabled(True)
        self.hex_receive.setGeometry(QtCore.QRect(620, 140, 71, 16))
        self.hex_receive.setTabletTracking(False)
        self.hex_receive.setAcceptDrops(False)
        self.hex_receive.setAutoFillBackground(False)
        self.hex_receive.setChecked(False)
        self.hex_receive.setAutoRepeat(False)
        self.hex_receive.setAutoExclusive(False)
        self.hex_receive.setTristate(False)
        self.hex_receive.setObjectName("hex_receive")
        self.s2__clear_button = QtWidgets.QPushButton(Form)
        self.s2__clear_button.setGeometry(QtCore.QRect(620, 160, 61, 31))
        self.s2__clear_button.setObjectName("s2__clear_button")
        self.timer_send_cb = QtWidgets.QCheckBox(Form)
        self.timer_send_cb.setGeometry(QtCore.QRect(260, 500, 71, 16))
        self.timer_send_cb.setObjectName("timer_send_cb")
        self.lineEdit_3 = QtWidgets.QLineEdit(Form)
        self.lineEdit_3.setGeometry(QtCore.QRect(350, 500, 61, 20))
        self.lineEdit_3.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.lineEdit_3.setObjectName("lineEdit_3")
        self.dw = QtWidgets.QLabel(Form)
        self.dw.setGeometry(QtCore.QRect(420, 500, 54, 20))
        self.dw.setObjectName("dw")
        self.label_62 = QtWidgets.QLabel(Form)
        self.label_62.setGeometry(QtCore.QRect(630, 0, 91, 20))
        self.label_62.setObjectName("label_62")
        self.label_63 = QtWidgets.QLabel(Form)
        self.label_63.setGeometry(QtCore.QRect(630, 20, 41, 16))
        self.label_63.setObjectName("label_63")
        self.SetAutoClear = QtWidgets.QCheckBox(Form)
        self.SetAutoClear.setEnabled(True)
        self.SetAutoClear.setGeometry(QtCore.QRect(620, 200, 71, 16))
        self.SetAutoClear.setTabletTracking(False)
        self.SetAutoClear.setAcceptDrops(False)
        self.SetAutoClear.setAutoFillBackground(False)
        self.SetAutoClear.setChecked(True)
        self.SetAutoClear.setAutoRepeat(False)
        self.SetAutoClear.setAutoExclusive(False)
        self.SetAutoClear.setTristate(False)
        self.SetAutoClear.setObjectName("SetAutoClear")
        self.ClearNumSet = QtWidgets.QLineEdit(Form)
        self.ClearNumSet.setGeometry(QtCore.QRect(650, 220, 41, 20))
        self.ClearNumSet.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.ClearNumSet.setObjectName("ClearNumSet")
        self.dw_2 = QtWidgets.QLabel(Form)
        self.dw_2.setGeometry(QtCore.QRect(620, 220, 31, 20))
        self.dw_2.setObjectName("dw_2")
        self.s3__openfile_button = QtWidgets.QPushButton(Form)
        self.s3__openfile_button.setGeometry(QtCore.QRect(620, 410, 61, 31))
        self.s3__openfile_button.setObjectName("s3__openfile_button")
        self.verticalGroupBox.raise_()
        self.verticalGroupBox_2.raise_()
        self.formGroupBox.raise_()
        self.s3__send_button.raise_()
        self.s3__clear_button.raise_()
        self.formGroupBox.raise_()
        self.hex_send.raise_()
        self.hex_receive.raise_()
        self.s2__clear_button.raise_()
        self.timer_send_cb.raise_()
        self.lineEdit_3.raise_()
        self.dw.raise_()
        self.label_62.raise_()
        self.label_63.raise_()
        self.SetAutoClear.raise_()
        self.ClearNumSet.raise_()
        self.dw_2.raise_()
        self.s3__openfile_button.raise_()

        self.retranslateUi(Form)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.formGroupBox.setTitle(_translate("Form", "串口设置"))
        self.s1__lb_1.setText(_translate("Form", "串口检测:"))
        self.s1__box_1.setText(_translate("Form", "检测串口"))
        self.s1__lb_2.setText(_translate("Form", "串口选择:"))
        self.s1__lb_3.setText(_translate("Form", "波特率:"))
        self.s1__box_3.setItemText(0, _translate("Form", "115200"))
        self.s1__box_3.setItemText(1, _translate("Form", "2400"))
        self.s1__box_3.setItemText(2, _translate("Form", "4800"))
        self.s1__box_3.setItemText(3, _translate("Form", "9600"))
        self.s1__box_3.setItemText(4, _translate("Form", "14400"))
        self.s1__box_3.setItemText(5, _translate("Form", "19200"))
        self.s1__box_3.setItemText(6, _translate("Form", "38400"))
        self.s1__box_3.setItemText(7, _translate("Form", "57600"))
        self.s1__box_3.setItemText(8, _translate("Form", "76800"))
        self.s1__box_3.setItemText(9, _translate("Form", "12800"))
        self.s1__box_3.setItemText(10, _translate("Form", "230400"))
        self.s1__box_3.setItemText(11, _translate("Form", "460800"))
        self.s1__lb_4.setText(_translate("Form", "数据位:"))
        self.s1__box_4.setItemText(0, _translate("Form", "8"))
        self.s1__box_4.setItemText(1, _translate("Form", "7"))
        self.s1__box_4.setItemText(2, _translate("Form", "6"))
        self.s1__box_4.setItemText(3, _translate("Form", "5"))
        self.s1__lb_5.setText(_translate("Form", "校验位:"))
        self.s1__box_5.setItemText(0, _translate("Form", "N"))
        self.open_button.setText(_translate("Form", "打开串口"))
        self.close_button.setText(_translate("Form", "关闭串口"))
        self.s1__lb_6.setText(_translate("Form", "停止位:"))
        self.s1__box_6.setItemText(0, _translate("Form", "1"))
        self.verticalGroupBox.setTitle(_translate("Form", "接收区"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("Form", "Tab 1"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab2), _translate("Form", "Tab 2"))
        self.verticalGroupBox_2.setTitle(_translate("Form", "发送区"))
        self.s3__send_text.setHtml(_translate("Form", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\"
        self.s3__send_button.setText(_translate("Form", "发送"))
        self.s3__clear_button.setText(_translate("Form", "清除发送"))
        self.formGroupBox1.setTitle(_translate("Form", "串口状态"))
        self.label.setText(_translate("Form", "已接收:"))
        self.label_2.setText(_translate("Form", "已发送:"))
        self.hex_send.setText(_translate("Form", "Hex发送"))
        self.hex_receive.setText(_translate("Form", "Hex接收"))
        self.s2__clear_button.setText(_translate("Form", "清除接收"))
        self.timer_send_cb.setText(_translate("Form", "定时发送"))
        self.lineEdit_3.setText(_translate("Form", "20"))
        self.dw.setText(_translate("Form", "ms/次"))
        self.label_62.setText(_translate("Form", "Author:Crazzy_M"))
        self.label_63.setText(_translate("Form", "V1.2"))
        self.SetAutoClear.setText(_translate("Form", "自动清除"))
        self.ClearNumSet.setText(_translate("Form", "10000"))
        self.dw_2.setText(_translate("Form", "超过"))
        self.s3__openfile_button.setText(_translate("Form", "打开文件"))

3.虚拟环境下生成exe(含图标)

3.1任务栏和exe左上角的图标添加

生成exe之前我们先给exe加个图标

基于python+pyqt5的串口助手
①图标对应的图片自己选择哈,格式是ico,随便找个网站就能转换。
基于python+pyqt5的串口助手


新建.qrc文件
名字自己命名

基于python+pyqt5的串口助手

我命名为images.qrc

基于python+pyqt5的串口助手
③images.qrc中添加代码
<RCC>
    <qresource prefix="/">
        <file>Ucom.ico</file>
     </qresource>
</RCC>

基于python+pyqt5的串口助手

④生成images.py文件

执行

pyrcc5 -o images.py images.qrc

首先保证Terminal中的路径是在刚才新建的images.qrc文件下

不然会提示错误

基于python+pyqt5的串口助手
通过cd指令将目录转至images.qrc文件下再执行
pyrcc5 -o images.py images.qrc

基于python+pyqt5的串口助手

执行命令之前是没有images.py

基于python+pyqt5的串口助手
执行命令之后
基于python+pyqt5的串口助手

images.py文件中是什么呢,其实就是将图片转换为了数据

基于python+pyqt5的串口助手

⑤将转换后的images.py引入主程序

import images

⑥在程序中调用

self.setWindowIcon(QIcon(':/Ucom.ico'))

基于python+pyqt5的串口助手

至此图标设置完成(注意要安装py2exe的包,不然有可能打包出来的图标会不显示)。

3.2 虚拟环境下生成EXE

如果你在运行环境下没装过其他的包,可以直接执行

pyinstaller -F --icon=Ucom.ico pyserial_demo.py -w

但是如果你安装的多余包过多,或者是以前项目安装了很多包就会导致打包的exe文件异常大,动辄300M+。

所以我们需要创建虚拟环境进行exe的打包,也就是为exe创建一个纯净的包环境。

①安装pipenv

pip install --user pipenv

②创建虚拟环境

pipenv shell

进入虚拟环境,操作环境就会变化

基于python+pyqt5的串口助手

③查看虚拟环境下有哪些包

pip list

下面是已经安装过包的list

基于python+pyqt5的串口助手

④安装所需要的包
所需的包

包说明pyqt5链接QTpyqt5-tools链接QTpyserial串口库matplotlib绘图所需的matlib包pyinstaller生成EXE所需的包py2exe生成exe所需的包(关系到exe任务栏和左上角图标能否正常显示

我是用的清华源比较快一点。

 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pyqt5
 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pyqt5-tools
 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pyserial
 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pyinstaller
 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ py2exe
 ...

⑤执行打包代码

虚拟环境下要安装pyinstaller 包,不然还是利用python默认的环境打包,打包出来的文件还是很大。

pyinstaller -F --icon=Ucom.ico pyserial_demo.py -w

⑥完成

在dist文件中可以找到生成的exe文件

基于python+pyqt5的串口助手

打开:

基于python+pyqt5的串口助手

3.3 功能演示

功能展示

★★★如有错误,欢迎指导!!!

Original: https://blog.csdn.net/qq_40147893/article/details/125569698
Author: Crazzy_M
Title: 基于python+pyqt5的串口助手

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/669331/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球