PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。

IoT 1年前 (2021) admin
378 0 0


PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。

代码之美



PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。



写在前面


前言



听到这首歌,大家应被其前奏深深吸引住吧。

人生就是不断试错、复盘、转化的过程,我大胆又学了一门语言Python,对于我这种有面向对象编程基础的人来说,上手非常简单,仅一周学习并完成了,完成这软件,按照我一贯的学习方法:

运筹帷幄之中,决胜千里之外。

先要规划自己要实现什么功能的软件,再去针对性地翻资料,爬坑在所难免,但可以投资自己买视频学,但是我也从来不相信会有馅饼掉下来,能有稍些的指点我便心满意足,别指望他人能给予你什么,终究会明白,别人的屋檐再大,都不如自己有把伞。

“难熬的日子总会过去,不信你回头看看,你已经在不知不觉中熬过了很多苦痛,很棒吧。”

所以,我也开源我上月春节假期学习到的PyQt5,并且基于PyQt5打造的一款跨平台的电脑串口调试助手(支持window、MacOS和 Linux),代码和安装包在文章末尾开源地址;

集成了市面上大多串口工具的功能,包括:

  •  自定义波特率

  •  自动换行

  •  RTS 控

  •  DTR 控

  •  Hex 发送和接收


PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。




1

开发必备工具



  • Python 3.8 环境

  • PyCharm 2020.1.1 x64

  • QT Designer 5.2


对于如何选择一款开发工具,我也是挑了蛮久的,还是选择熟悉强大的IDEA系列软件,再配合QT Designer使用起来,非常Nice。下面分享下,我的快捷键,能使你的开发效率加倍。


纯技术公众号

PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。

1

PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。

PyCharm 如何集成 QT Designer

1.1 UI代码 -->可视化

QT Designer 为我们提供了将UI代码可视化的实现,打开下面终端并配置在IDE就可以了!


指令终端


Python38-32Libsite-packagespyqt5_toolsQtbindesigner.exe

PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。

1.2 可视化 -->UI代码

同样地,QT Designer 为我们提供了将可视化转UI代码的实现!


指令终端


终端:Python38-32Libsite-packagespyqt5_toolsQtbindesigner.exe

参数:-m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py


PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。


1.3 打包成 exe 软件

QT Designer 为我们提供了将整个工程打包成执行文件:


指令终端


终端:Python38-32Libsite-packagespyqt5_toolsQtbindesigner.exe

参数:-F -w $FileName$


PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。


1.4 如何自定义控件

在开发过程中,欲要在QT Designer实现自定义控件如何做呢?看我操作过程!

 

PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。


     那么问题来了,如何移除自定义控件呢?


PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。



3

代码结构说明


3.1

PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。

串口通讯应用层封装



  • 包括串口异常中断处理;

  • 提供上层应用接口有配置、发送和接收;

  • 子线程和信号槽应用实现无缝读取串口通讯接收到的数据给上位机;


class UartRecieveThread(QThread):
    def __init__(selfrun):
        super(UartRecieveThreadself).__init__()
        self.runfun 
run
    def run(self):
        self.runfun()
class UartSerial(QObject):
    # 定义一个信号变量,1个参数
    signalRecieve 
= pyqtSignal(object)
    CODE_RECIEVE, CODE_DISCONNECT = 01

    def __init__(self):
        super(UartSerial, self).__init__()
        self.mThread 
= UartRecieveThread(self.data_receive)  # 创建线程
        self.mSerial = serial.Serial()
        self.data_num_received = 0

    def init(self, _port="/dev/ttyUSB0", _baudrate=115200, _bytesize=8, _stopbits="N", _parity=serial.PARITY_NONE):
        self.mSerial.port 
= _port
        self.mSerial.baudrate = _baudrate
        self.mSerial.bytesize = _bytesize
        self.mSerial.stopbits = _stopbits
        self.mSerial.parity = _parity
        self.data_num_received = 0

    def is_port_open(self, _port_name, _baudrate):
        try:
            self.mSerial.port 
= _port_name
            self.mSerial.baudrate = _baudrate
            return not self.mSerial.isOpen()
        except Exception:
            return False

    # 关闭串口
    def port_close(self, _port_name, _baudrate):
        self.mSerial.port 
= _port_name
        self.mSerial.baudrate = _baudrate
        try:
            self.mSerial.close()
        except:
            return False
        self.mThread.quit()
        return True

    # 串口检测
    def get_all_port(self):
        # 检测所有存在的串口,将信息存储在字典中
        self.port_list_name 
= []
        port_list = list(serial.tools.list_ports.comports())
        i = 0

        if len(port_list) <0:
            return []
        else:
            for port in port_list:
                i = i + 1
                self.port_list_name.append(port[0])

        return self.port_list_name

    # 打开串口
    def try_port_open(self, _port, _baudrate=115200):
        self.mSerial.port 
= _port
        self.mSerial.baudrate = _baudrate
        try:
            self.mSerial.open()
        except:
            return False
        if not self.mThread.isRunning():
            self.mThread.start()
        return True

    def set_rts(self, IsTrue):
        self.mSerial.setRTS(IsTrue)

    def set_dts(self, IsTrue):
        self.mSerial.setDTR(IsTrue)

    def get_rts(self):
        return self.mSerial.rts

    def get_dts(self):
        return self.mSerial.dtr

    def set_bytesize(self, _bytesize):
        self.mSerial.bytesize 
_bytesize

    def set_parity(self, _parity):
        self.mSerial.parity 
_parity

    def set_stopbits(self, _stopbits):
        self.mSerial.stopbits 
= _stopbits

    # 接收数据
    def data_receive(self):
        while True:
            data 
= {}
            try:
                num = self.mSerial.inWaiting()
            except:
                self.mSerial.close()
                data['code'] = self.CODE_DISCONNECT
                data['data'] = 0
                data['length'] = 0
                self.signalRecieve.emit(data)
                return None
            if num > 0:
                if self.mSerial.isOpen():
                    buff = self.mSerial.read(num)
                    data['code'] = self.CODE_RECIEVE
                    data['data'] = buff
                    data['length'] = len(buff)
                    self.signalRecieve.emit(data)
            time.sleep(0.1)

    # 设置回调函数
    def setCallBack(self, funtion):
        self.signalRecieve.connect(funtion)

    # send data
    def send_data(self, buff="", isHexSend=False, _port="", _baudrate=115200):
        if buff !
"":
            # 非空字符串
            if isHexSend:
                # hex发送
                buff = buff.strip()
                send_list = []
                while buff != '':
                    try:
                        num = int(buff[0:2], 16)
                    except ValueError:
                        return None
                    buff = buff[2:].strip()
                    send_list.append(num)
                buff = bytes(send_list)
            num = self.mSerial.write(buff)



3.2

PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。

自定义的实现




在实现某些功能时候,发现自带的控件无法满足需求时候,我们只能自定义控件,我重写了几个控件:

1 、重写 QComboBox

为了实现能自定义波特率,比如用户输入74880;

class MyQComBox(QComboBox):
    popupAboutToBeShown 
= pyqtSignal()  # 创建一个信号

    def showPopup(self):  # 重写showPopup函数
        super(MyQComBox, self).showPopup()
        self.popupAboutToBeShown.emit()  # 发送信号

2 、重写 QWidget

为了能够全局监听键盘按键,实现一键清空数据接受栏;

class MineWidget(QWidget):

    # 定义一个信号变量,1个参数
    signalMineWidget 
= pyqtSignal(object)

    def set_connect_key_press(self, fun):
        self.signalMineWidget.connect(fun)

    # 检测键盘回车按键
    def keyPressEvent(self, event):
        self.signalMineWidget.emit(event.key())

    def mousePressEvent(self, event):
        self.signalMineWidget.emit(event.button())


3 、接受数据并显示

这里要特别说明的是,在解码时候,特要指明 utf-8编码,以及带上 ignore表示接受解码失败异常;


def at_callback_handler(obj):
    if obj['code'] 
== 1:
        if ui.bt_open_off_port.text() != '打开串口':
            QMessageBox.critical(MainWindow, '错误信息''串口异常断开!')
            # 面板可操作
            checkoutPortStatus(True)
            ui.bt_open_off_port.setText('打开串口')
            refreshPort()
    else:
        buff = (obj['data'])
        now_time = datetime.now()  # 获取当前时间
        # new_time = now_time.strftime('[%H:%M:%S]')  # 打印需要的信息,依次是年月日,时分秒,注意字母大小写
        if ui.checkBox_show_hex.checkState():
            out_s = ''
            for i in range(0, len(buff)):
                out_s = out_s + '
{:02X}'.format(buff[i]) + ' '

            if ui.checkBox_show_add_ctrl.checkState():
                ui.textBrowserShow.append(out_s)
            else:
                ui.textBrowserShow.insertPlainText(out_s)
            ui.textBrowserShow.moveCursor(QTextCursor.End)
        else:
            try:
                if ui.checkBox_show_add_ctrl.checkState():
                    ui.textBrowserShow.append(buff.decode('utf-8''ignore'))
                else:
                    ui.textBrowserShow.insertPlainText(buff.decode('utf-8''ignore'))

                ui.textBrowserShow.moveCursor(QTextCursor.End)
            except:
                # 乱码显示
                pass



4

后面


最后,我们看看效果吧!
关注本微信公众号 徐宏blog 发送 210317 以获取全部代码!PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。

PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。


-推荐阅读-

点击文字即可阅读全文


☞ 2019年年终总结:平凡的我,仍然在平淡的生活里打拼,寻找未来的曙光。

 2020年终总结:跌跌撞撞,沉下心来,不卑不燥,欲戴王冠,必承其重。

☞ 基于SpringBoot私有服务器对接阿里云物联网服务器,实现M2M数据流。

 我回来了,深度自研开源物联网架构

 开源架构XClouds专题|私有云之天猫精灵等平台对接Oauth2.0协议详解!

☞ esp32蓝牙配网高度封装,集成简单、使用简单,提高开发效率!

 重磅开源,微信小程序ble蓝牙配网乐鑫esp32,开源奉献物联网;


部分图片摘取网络  侵删

PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。

原文始发于微信公众号(徐宏blog):PyQT5上位机开发,如何自定义控件,入门做一个上位电脑串口调试软件,全部开源。

相关文章

暂无评论

暂无评论...