如何实现点击Tkinter按钮弹出messagebox显示串口读取的充电器数据
问题原因
- Tkinter主线程被阻塞:
get_com()函数内置无限while True循环+time.sleep(),会长期占用UI主线程资源,导致Tkinter无法处理点击、弹窗等UI事件,永远执行不到messagebox相关代码 - 布局缺失:按钮创建后没有调用
pack()/grid()等布局方法,不会在窗口中显示,无法触发点击事件 - 变量作用域错误:
testvars是get_com()内部的局部变量,show_com11()无法直接访问;且get_com()每次读取完数据后都会调用init_testvars()重置所有参数,就算能拿到变量也都是初始0值 - 代码细节错误:串口参数拼写错误
ser.stopbites应为ser.stopbits、换行符写反为/n应为\n、当前代码串口硬编码为COM9和你要调试的COM11不匹配、colored()生成的带颜色控制字符无法在Tkinter的messagebox中正常显示会出现乱码
修复方案
- 去掉
get_com()中的无限循环,改成点击按钮时单次读取串口数据 - 补充按钮布局逻辑,确保按钮可以正常显示点击
- 调整变量作用域,让读取到的测试参数可以正常返回给弹窗调用
- 修正所有细节拼写错误,移除messagebox中不支持的带颜色字符串
- 串口读取逻辑调整为单次读取后直接返回数据,不要提前重置有效参数
修改后可运行代码
# import modules from tkinter import * from tkinter import messagebox import serial import time import sys import datetime global testflag testflag = 0 # 串口配置调整为COM11,修正stopbits参数错误 try: ser = serial.Serial('COM11') ser.baudrate = 4800 ser.bytesize = 8 ser.parity = 'N' ser.stopbits = 1 ser.timeout = 40 except: print("#################################################") print("# Serial Port could not be found. Exiting ..... #") print("#################################################") sys.exit() # configure workspace ws = Tk() ws.title("COM Ports") ws.geometry('500x150') # 修改get_com为单次读取,返回有效数据 def get_com(): testvars = {} def init_testvars(): testvars['Capacity'] = 0 testvars['Vpack'] = 0 testvars['V1'] = 0 testvars['V2'] = 0 testvars['V3'] = 0 testvars['Current'] = 0 testvars['Temp'] = 0 testvars['Version'] = 0 testvars['Cycles'] = 0 init_testvars() # 移除无限循环,单次读取数据 lenread = 0 while lenread < 1: outBytes = ser.read() lenread = len(outBytes) time.sleep(4) data_left = ser.inWaiting() outBytes += ser.read(data_left) outStr = outBytes.decode() now = datetime.datetime.now() print ("> " + now.strftime("%Y-%m-%d %H:%M:%S") + " <") findsum = outStr.find('V1') + outStr.find('V2')+outStr.find('V3') findsum += outStr.find('VPACK') + outStr.find('CAPACITY') if findsum != -5: nindex = outStr.find('V1') if nindex != -1: testvars['V1'] = float(outStr[nindex+23:nindex+28]) nindex = outStr.find('V2') if nindex != -1: testvars['V2'] = float(outStr[nindex+23:nindex+28]) nindex = outStr.find('V3') if nindex != -1: testvars['V3'] = float(outStr[nindex+23:nindex+28]) nindex = outStr.find('VPACK') if nindex != -1: testvars['Vpack'] = float(outStr[nindex+23:nindex+29]) nindex = outStr.find('CAPACITY') if nindex != -1: testvars['Capacity'] = float(outStr[nindex+11:nindex+13]) # 计算 pass/fail 结果,移除不支持的colored样式 v1_3 = abs(testvars['V1'] - testvars['V3']) v1_2 = abs(testvars['V1'] - testvars['V2']) v2_3 = abs(testvars['V2'] - testvars['V3']) if ((v1_3 < 50) and (v1_2 < 50) and (v2_3 < 50)): pass_fail = "\n#######PASS########" else: pass_fail = "\n#######FAIL#######" # 返回读取到的参数和结果 return testvars, pass_fail def show_com11(): testvars, pass_fail = get_com() # 修正换行符错误 v1 = "V1 = {:.3f} V".format(testvars['V1']) v2 = "\nV2 = {:.3f} V".format(testvars['V2']) v3 = "\nV3 = {:.3f} V".format(testvars['V3']) total = v1 + v2 + v3 + pass_fail ser.close() messagebox.showinfo("COM11", str(total)) # 补充按钮布局 com11 = Button(ws, text="COM11", command = show_com11) com11.pack(pady=50) ws.mainloop()
内容的提问来源于stack exchange,提问作者frustrated_student
相关产品推荐
相关产品推荐

