利用python快速开发一个上位机软件
PyQt5+QtDesigner学习记录
标签: 漂流小江 2020年2月6日
一、串口调试助手
1.QT界面实现
(1)界面面图片展示
(图示1处函数为自定义函数)
)
(2)界面代码展示
# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'chuankou.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_MainWindow(object):def setupUi(self, MainWindow):MainWindow.setObjectName("MainWindow")MainWindow.resize(775, 600)self.centralwidget = QtWidgets.QWidget(MainWindow)self.centralwidget.setObjectName("centralwidget")self.sendbutton = QtWidgets.QPushButton(self.centralwidget)self.sendbutton.setGeometry(QtCore.QRect(115, 266, 91, 31))font = QtGui.QFont()font.setPointSize(15)self.sendbutton.setFont(font)self.sendbutton.setObjectName("sendbutton")self.sendcom = QtWidgets.QComboBox(self.centralwidget)self.sendcom.setGeometry(QtCore.QRect(100, 60, 131, 51))font = QtGui.QFont()font.setPointSize(15)self.sendcom.setFont(font)self.sendcom.setLayoutDirection(QtCore.Qt.LeftToRight)self.sendcom.setObjectName("sendcom")self.sendcom.addItem("")self.sendcom.setItemText(0, "")self.sendbot = QtWidgets.QComboBox(self.centralwidget)self.sendbot.setGeometry(QtCore.QRect(100, 160, 131, 41))font = QtGui.QFont()font.setPointSize(15)self.sendbot.setFont(font)self.sendbot.setObjectName("sendbot")self.sendbot.addItem("")self.sendbot.addItem("")self.label = QtWidgets.QLabel(self.centralwidget)self.label.setGeometry(QtCore.QRect(20, 60, 71, 41))font = QtGui.QFont()font.setPointSize(15)self.label.setFont(font)self.label.setAlignment(QtCore.Qt.AlignCenter)self.label.setObjectName("label")self.label_2 = QtWidgets.QLabel(self.centralwidget)self.label_2.setGeometry(QtCore.QRect(20, 150, 71, 41))font = QtGui.QFont()font.setPointSize(15)self.label_2.setFont(font)self.label_2.setAlignment(QtCore.Qt.AlignCenter)self.label_2.setObjectName("label_2")self.recvddata = QtWidgets.QTextEdit(self.centralwidget)self.recvddata.setGeometry(QtCore.QRect(240, 20, 371, 281))font = QtGui.QFont()font.setPointSize(13)self.recvddata.setFont(font)self.recvddata.setObjectName("recvddata")self.label_3 = QtWidgets.QLabel(self.centralwidget)self.label_3.setGeometry(QtCore.QRect(350, 310, 131, 41))font = QtGui.QFont()font.setPointSize(15)self.label_3.setFont(font)self.label_3.setAlignment(QtCore.Qt.AlignCenter)self.label_3.setObjectName("label_3")self.inputdata = QtWidgets.QTextEdit(self.centralwidget)self.inputdata.setGeometry(QtCore.QRect(260, 360, 321, 81))font = QtGui.QFont()font.setPointSize(15)self.inputdata.setFont(font)self.inputdata.setObjectName("inputdata")self.label_4 = QtWidgets.QLabel(self.centralwidget)self.label_4.setGeometry(QtCore.QRect(500, 470, 151, 41))font = QtGui.QFont()font.setPointSize(15)self.label_4.setFont(font)self.label_4.setAlignment(QtCore.Qt.AlignCenter)self.label_4.setObjectName("label_4")self.senddata = QtWidgets.QPushButton(self.centralwidget)self.senddata.setGeometry(QtCore.QRect(120, 380, 91, 31))font = QtGui.QFont()font.setPointSize(15)self.senddata.setFont(font)self.senddata.setObjectName("senddata")self.checknline = QtWidgets.QCheckBox(self.centralwidget)self.checknline.setGeometry(QtCore.QRect(210, 460, 211, 51))font = QtGui.QFont()font.setPointSize(15)self.checknline.setFont(font)self.checknline.setLayoutDirection(QtCore.Qt.LeftToRight)self.checknline.setObjectName("checknline")MainWindow.setCentralWidget(self.centralwidget)self.menubar = QtWidgets.QMenuBar(MainWindow)self.menubar.setGeometry(QtCore.QRect(0, 0, 775, 18))self.menubar.setObjectName("menubar")MainWindow.setMenuBar(self.menubar)self.statusbar = QtWidgets.QStatusBar(MainWindow)self.statusbar.setObjectName("statusbar")MainWindow.setStatusBar(self.statusbar)self.retranslateUi(MainWindow)self.sendbutton.clicked.connect(MainWindow.open_com)self.sendcom.activated['QString'].connect(MainWindow.port_changed)self.sendbot.activated['QString'].connect(MainWindow.baud_changed)self.senddata.clicked.connect(MainWindow.senddatatocom)QtCore.QMetaObject.connectSlotsByName(MainWindow)def retranslateUi(self, MainWindow):_translate = QtCore.QCoreApplication.translateMainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))self.sendbutton.setStatusTip(_translate("MainWindow", "点击连接"))self.sendbutton.setText(_translate("MainWindow", "连接"))self.sendbot.setItemText(0, _translate("MainWindow", "9600"))self.sendbot.setItemText(1, _translate("MainWindow", "115200"))self.label.setText(_translate("MainWindow", "串口"))self.label_2.setText(_translate("MainWindow", "波特率"))self.label_3.setText(_translate("MainWindow", "接收显示"))self.label_4.setText(_translate("MainWindow", "发送数据"))self.senddata.setText(_translate("MainWindow", "发送"))self.checknline.setText(_translate("MainWindow", "发送新行"))
1.界面逻辑实现代码
(1)逻辑代码展示
import serial
import sys
import struct
import serial.tools.list_ports
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import numpy as np
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import *
from chuankou import *########################
#函数区
####################################################
# 串口函数区
def get_com_list():Com_List = []plist = list(serial.tools.list_ports.comports())if len(plist) > 0:for i in range(len(plist)):Com_List.append(list(plist[i])[0])return Com_List######################################################创建主界面
class MyWindow(QMainWindow, Ui_MainWindow):def __init__(self, parent=None):super(MyWindow, self).__init__(parent)self.setupUi(self)self.setWindowIcon(QIcon('serialscope.ico'))#程序的图标#创建一个定时器self.sendbutton.setToolTip('点击打开串口')# 初始化一个定时器,防止while循环读串口时陷入死循环self.timer = QTimer(self) # 初始化一个定时器self.timer.timeout.connect(self.time_out) # 计时结束调用time_out()def show_dialog(self, str=''):# 创建QDialog对象dialog = QDialog()# 创建按钮到新创建的dialog对象中lb = QLabel(str, dialog)lb.move(50, 50)# btn = QPushButton('ok', dialog)# 移动按钮,设置dialog的标题# btn.move(50, 50)dialog.setWindowTitle("Dialog")# 设置窗口的属性为Qt.ApplicationModal模态,用户只有关闭弹窗后,才能关闭主界面dialog.setWindowModality(Qt.NonModal)dialog.exec_()#定时100ms读一次数据,未用while,防止程序陷入死循环def time_out(self): # 按时接收数据global ser, timer_value# data = ser.readline()data = ser.read_all() # 读取串口中的数据if data != b'':data = data.decode('utf-8')self.recvddata.append(data)self.timer.start(timer_value) # 原本不需要重启,是考虑到变时定时#######################def open_com(self):global ser, serialPort, baudRate, com_listcom_list = get_com_list() # 得到可用串口if com_list != []: # 如果一切正常,串口正常打开if serialPort != None: # 如果也没出过什么叉子ser.port = serialPortser.baudrate = baudRateif self.sendbutton.text() == '连接':ser.open() # 上述操作已经打开串口,不能再次打开端口self.timer.start(timer_value) # 定时处理一次接收的数据self.sendbutton.setText("关闭")self.sendbutton.setToolTip('点击关闭串口')print('串口已连接')# while True:# data = ser.read_all() # 读取串口中的数据# if data != b'':# data = data.decode('utf-8')# print(data)else:self.timer.stop()ser.close() # 关闭端口self.sendbutton.setText("连接")self.sendbutton.setToolTip('点击打开串口')print('串口已断开')else: # 如果中途出过叉子,先修复myWin.port_combo.clear()for i in range(len(com_list)): # 将可用串口填充到下拉框myWin.sendcom.addItem(com_list[i])serialPort = com_list[0] # 串口号else: # 已经坏透了,显示提示框serialPort = NonemyWin.sendcom.clear()myWin.show_dialog(str='请先打开串口')#向串口发送数据def senddatatocom(self):global serialPort, serif self.sendbutton.text() == '关闭'and serialPort != None:send_str=self.inputdata.toPlainText()state_checknline=self.checknline.isChecked()if state_checknline == True:#选择是否换行print('发送新行')send_str += '\r\n'ser.write(send_str.encode('utf-8'))#将要发送的数据写入串口print('发送数据为:'+send_str)else:self.show_dialog(str='请先打开串口')#改变串口def port_changed(self, text):global serialPortserialPort = textprint('串口:' + serialPort)ser.port = serialPort#改变波特率def baud_changed(self, text):global baudRatebaudRate = int(text)print(baudRate)ser.baudrate=baudRate
####################################################
#全局变量及先行代码
app = QApplication(sys.argv)
myWin = MyWindow()
myWin.show()
# myWin.Port_send() #开机有可用串口则自动打开串口
baudRate = 115200 # 波特率
timer_value=100
#################################################
ser=serial.Serial(timeout=0.5)
com_list=get_com_list() #得到可用串口
if com_list!=[]:for i in range(len(com_list)): # 将可用串口填充到下拉框myWin.sendcom.addItem(com_list[i])serialPort = com_list[0] # 串口号
else:serialPort = NonemyWin.show_dialog(str='请先打开串口')sys.exit(app.exec_())
(2)逻辑效果展示
二、PyQt5使用技巧总结
1.多线程的三种使用
*背景:
*在PyQt中所有的窗口都在UI主线程中(就是执行了QApplication.exec()的线程,在这个线程中执行耗时的操作阻塞UI线程,从而导致窗口停止响应,加入多线程机制会很好的解决这个问题。
(1)计时器模块QTimer
实现:
#首先引入QTimer模块from PyQt5.QtCore import Qt, QTimer
#****************************************************# 初始化一个定时器,防止while循环读串口时陷入死循环self.timer = QTimer(self) # 初始化一个定时器self.timer.timeout.connect(self.time_out) # 计时结束调用time_out()
#****************************************************#定时100ms读一次数据,未用while,防止程序陷入死循环def time_out(self): # 按时接收数据passself.timer.start(timer_value) # 原本不需要重启,是考虑到变时定时
#****************************************************self.timer.start(timer_value) # 定时处理一次接收的数据,timer_value为设置的时间,单位ms
#****************************************************self.timer.stop()#停止计时
(2)线程模块QThread
实现:
#首先引入QTimer模块from PyQt5.QtCore import Qt, QTimer
#****************************************************#要使用QThread开始一个线程,需创建其子类,覆盖其QThread.run()函数,#如:class Thread(QThread):def__init__(self):super(Thread,self).__init__()def run(self):#相关代码pass#****************************************************#接下来创建一个新的线程thread=Thread()thread.start()
#****************************************************
此笔记写的有些粗糙,更详细笔记我已在本人公众号更新,或者想要了解更多或者想要获取该工程代码请关注微信公众号“漂流小江”,还可以在b站观看小江的视频课程。
利用python快速开发一个上位机软件相关推荐
- 什么是核心竞争力——源自半导体行业,一个上位机软件开发工程师
到底什么是核心竞争力 ----来自半导体行业,一个上位机软件开发工程师 我的工作侧重于软件二次开发,因行业问题,软件需要对电机,泵等硬件进行通信,按照一定的顺序对其进行控制,对Wafer进行加工,以达 ...
- windows和Linux利用Python快速搭建一个网站
windows和Linux利用Python快速搭建一个网站 一.windows 步骤1:安装Python3(自行百度) 步骤2:在cmd窗口输入ipconfig查看本机ip地址,IPV4那一行.如:1 ...
- 用python快速开发一个实用的socket服务器
用python快速开发一个实用的socket服务器 - 吴尔平 - 博客园 用python快速开发一个实用的socket服务器 首先,要明白不是所有的socket服务都需要高性能.如果要求高性能,使用 ...
- java开发plc上位机软件开发_上位机开发之西门子PLC-S7通信实践
写在前面: 就目前而言,在中国的工控市场上,西门子仍然占了很大的份额,因此对于上位机开发而言,经常会存在需要与西门子PLC进行通信的情况.然后对于西门子PLC来说,通信方式有很多,下面简单列举一下: ...
- python连接linux堡垒机_利用Python Paramiko开发linux堡垒机
1.Paramiko模块下的demo.py程序 前面利用Python中的Paramiko模块可以进行SSH的连接,以及用来传送文件(SFTP),但是无论是哪一种方式,连接都是短暂的,并非是长连的,即一 ...
- 如何用 Python 快速开发一个区块链数据结构?
作者 | arjuna sky kok 整理 | Aholiab 出品 | 区块链大本营(blockchain_camp) 根据IEEE此前的一项调查,Python已成为最受开发者欢迎的语言之一.由于 ...
- python自动点名程序_利用python+tkinter开发一个点名软件
from win32com.client importDispatchfrom tkinter import * importtkinter as tkfrom PIL importImagefrom ...
- python自动垃圾分类_现在垃圾都得分类,如何利用Python快速实现一个垃圾分类APP?...
最近北京开始实行垃圾分类,导致大家对垃圾的研究热度突然涨高,垃圾们也纷纷表示从来没有获得过这么高的关注度.其实,上海市去年已经开始实行,网上已经有不少成熟的教程了,像什么<垃圾分类从入门到精通& ...
- 利用python快速搭建一个ftp文件服务器
点击上方"AI搞事情"关注我们 前置条件:python环境 一行命令 python -m http.server 端口号 # python3 python -m SimpleHTT ...
最新文章
- Python OpenCV 图片拆分与拼接
- VS2010解决方案位置不对和改变程序字体的方案
- PrepareStatement 和Statement 的区别?
- python字符串解析_Python-字符串解析-正则-re
- Mysql yum 安装后,一些重要的文件路径
- java主动对象模式_POCO的主动对象
- 中国喷淋泵行业市场供需与战略研究报告
- 无法将该对象添加到ldap服务器_Minecraft 基岩版 Ubuntu服务器搭建(三)
- 多易教育大数据课程学费调整通知
- 计算机管理的服务打不开,Windows 系统服务无法打开解决方法+操作命令详解
- Facebook 应用开发认证和授权登录流程
- [论文总结] 科技论文英语写作笔记1
- 小程序页面浏览到底部触发事件
- 投资黄金,当然选贸易场行员平台真宝金业,安全有保障,返佣高,平仓返。
- 计算机组成原理 原码,反码,补码,移码
- CCS3.3 新建工程遇到的问题
- Serial Programming Guide for POSIX Operating Systems
- css背景透明(css背景透明度怎么设置)
- 前端的岗位以及初步了解
- Validator框架的使用
热门文章
- Flex Builder3调试运行提示没有安装Flash Player
- 今夕何夕(思路详解)
- 2-Pyridinylacetic acid,2-吡啶基乙酸,CAS号:13115-43-0
- 物联网开发笔记(80)- 使用Micropython开发ESP32开发板之通过IIC接口控制TM1650四位共阴数码管模块
- 怎么解密PDF文档?这三款解密方法亲测实用
- Vue 点击按钮跳转其他链接
- 校友会小程序开发笔记四:UI基本元素设计
- 前端(js/css/html)那些小的知识点,持续更新......
- 校招 | 微软萌新记:实习初体验
- 3d动画用云渲染靠谱吗?