我是OOP的新手,我正在尝试为自己创建GUI。 我想制作一个模拟器程序。我正在用Arduino读取串行数据。
我的问题是:
示例代码:
from tkinter import *
import serial
import serial.tools.list_ports as ports
switch=False
class Application(Frame):
def __init__(self,master,*args,**kwargs):
Frame.__init__(self,*args,**kwargs)
ratios=self.GetScreenRatio()
self.CreateCanvas()
self.PackWidgets()
def updateGui(self):
self.update()
def CreateCanvas(self):
self.canvas=Canvas(root,width=self.winfo_screenwidth(),height=self.winfo_screenheight())
self.canvas.pack()
def GetScreenRatio(self):
self.screen_width = self.winfo_screenwidth()/1920
self.screen_height = self.winfo_screenheight()/1080
def PackWidgets(self):
x_ratio=self.screen_width
y_ratio=self.screen_height
letter_ratio=(x_ratio+y_ratio)/2
self.start_button=Button(root,text='Start',command=self.Start,activeforeground='white',
bg='green',activebackground='green',fg='white',width=21,height=2,font='bold')
self.start_button.place(x=120*x_ratio,y=800*y_ratio)
self.stop_button=Button(root,text='Stop',command=self.Stop,activeforeground='white',
bg='red',activebackground='red',fg='white',width=21,height=2,font='bold')
self.stop_button.place(x=760*x_ratio,y=800*y_ratio)
self.quit_button=Button(root,text='Quit',bg='black',activebackground='black',command=root.destroy,
fg='white',activeforeground='white',width=21,height=2,font='bold')
self.quit_button.place(x=1400*x_ratio,y=800*y_ratio)
self.bridge_pointer=Label(root,text='Híd neve:',font=("Courier",round(50*letter_ratio)),fg='#0078ef')
self.bridge_pointer.place(x=1*x_ratio,y=1*y_ratio)
self.bridge_name=Label(root,font=("Courier",round(50*letter_ratio)),fg='#0078ef')
self.bridge_name.place(x=400*x_ratio,y=1*y_ratio)
self.bridge_value=Label(root,text='0.0',font=("Courier",round(200*letter_ratio)),fg='#0078ef')
self.bridge_value.place(x=200*x_ratio,y=200*y_ratio)
self.value_prefix=Label(root,text='Kg',fg='#0078ef',font=("Courier", round(100*letter_ratio)))
self.value_prefix.place(x=390*x_ratio,y=480*y_ratio)
teglalap=self.canvas.create_rectangle(1*x_ratio,1*y_ratio,50*x_ratio,
50*y_ratio,fill="#0078ef",width=2)
teglalap2=self.canvas.create_rectangle(987*x_ratio,612*y_ratio,1165*x_ratio,
602*y_ratio,fill="#909090",width=2)
teglalap3=self.canvas.create_rectangle(1215*x_ratio,612*y_ratio,1360*x_ratio,
602*y_ratio,fill="#909090",width=2)
def Start(self):
self.run()
def Stop(self):
#Stop serial connection(stop the Application.run() func)
pass
def run(self):
self.MakeSerial()
self.Update()
root.mainloop()
def MakeSerial(self):
try:
for ee in list(ports.comports()):
if ee.serial_number=='55639313633351A07142':
usb=ee.device
self.ser=serial.Serial(usb,baudrate=57600,timeout=2)
except UnboundLocalError:
root.destroy()
print('Nincs csatlakoztatva az Arduino! ')
def Update(self):
try:
if self.ser.isOpen():
data = self.ser.readline(self.ser.inWaiting())
self.bridge_value['text']=data
self.after(10,self.Update)
print(data)
else:
print('Portot nem lehet megnyitni!')
except serial.serialutil.SerialException:
print("Soros kapcsolat megszakadt")
except AttributeError:
pass
root=Tk()
root.state('zoomed')
window=Application(root)
有什么好的建议吗?
这是错误:
for c in list(self.children.values()): c.destroy()
File "C:XXXXX\GUI proba.py", line 77, in destroy
self.Stop() RecursionError: maximum recursion depth exceeded
答案 0 :(得分:0)
评论:当我按下退出按钮时,我的窗口冻结,无法执行任何操作
我超载了Application.destroy()
中调用的root.destroy()
。在这里我们称为root.destroy()
,这将导致无限循环。
将def destroy(...
更改为def quit(...
问题:如何使用停止按钮停止run()函数
使用标志变量,例如self.stopUpdate
如下:
def __init__(self,master,*args,**kwargs):
...
self.stopUpdate = None
self.MakeSerial()
def PackWidgets(self):
...
self.quit_button=Button(..., command=self.quit, ...
def quit(self):
self.Stop()
# Wait until Update returns
while self.stopUpdate:
time.sleep(1)
root.destroy()
def Start(self):
self.stopUpdate = False
self.Update()
def Stop(self):
self.stopUpdate = True
def Update(self):
if self.stopUpdate:
# Indicates Update returns, for self.destroy(...
self.stopUpdate = False
return
try:
...
全部删除
#def run(self): # self.MakeSerial() # self.Update() # root.mainloop()
self.MakeSerial()
移至__init__(...
self.Update()
移至self.Start(...
root.mainloop()
移动到脚本底部。 注意:
用一个try: ... except:
块捕获多个异常是很糟糕的。
将一个用于.ser.readline(...
,将一个用于=data