from Tkinter import *
import tkFileDialog
import tkMessageBox
import os
import ttk
import serial
import timeit
import time
######################################################################################
class MyApp:
def __init__(self, parent):
########################################################
#Setup Frames
self.MiddleFrame = Frame(parent) #Middle Frame
self.MiddleFrame.pack()
#GLOBAL VARIABLES
self.chip_number = 0 #number of chip testing
###########################################
#Middle Frame setup
Label(self.MiddleFrame, text='Done').grid(row=8, column=1, sticky = E)
self.Done = Canvas(self.MiddleFrame, bg="yellow", width=10, height=10)
self.Done.grid(row=8, column=2)
Label(self.MiddleFrame, text='Chip Number:').grid(row=9, column=1, sticky = E)
#start button
self.button1 = Button(self.MiddleFrame,state=NORMAL, command= self.start_pre)
self.button1["text"]= "START"
self.button1.grid(row=1, column=2, sticky = E)
###########################################
#Action of Start Button
def start_pre(self):
x = 0
while x<10000:
self.start_button()
x=x+1
#Talking to Board
def start_button(self):
#increase chip count number and update
self.chip_number += 1
Label(self.MiddleFrame, text=str(self.chip_number)).grid(row=9, column=2, sticky = E)
#reset-yellow
self.reset_color()
print "Still Working", self.chip_number
self.Done.configure(background="green")
self.Done.update_idletasks()
###############################################################
#Color Boxes
#Reset
def reset_color(self):
self.Done.configure(background="yellow")
self.Done.update_idletasks()
###############################################################################################################
#Start Programs
root = Tk() #makes window
root.title("Interface")
myapp = MyApp(root) #this really runs program
root.mainloop() #keep window open
通过我的程序,我首先按下开始按钮。 我将打印“仍在工作”,GUi将一遍又一遍地更新芯片编号和闪烁灯。启动按钮转到将执行10000次的功能。然而,在3000次迭代之后,gui冻结,但程序仍然打印“仍在工作”。如何防止gui崩溃?
答案 0 :(得分:2)
您的代码存在许多问题。首先,这从根本上是有缺陷的:
while self.stop == True:
self.start_button()
time.sleep(0.5)
您根本不能指望GUI能够像这样的代码正常运行。作为一般经验法则,您永远不应该拥有GUI调用的主线程sleep
。导致sleep
阻止事件循环处理任何事件,包括低级事件,例如刷新屏幕的请求。
在stackoverflow上已经多次询问和回答sleep
的使用。您可能会发现其中一些问题很有用。例如,
您还有另一个属于内存泄漏问题的问题。从那个while循环开始,你无限期地调用self.start_button()
。这种情况大约每秒发生一次,因为在循环中调用睡眠半秒,在start_button
中调用另外半秒。
每次调用start_button
时,都会创建另一个标签小部件,并将其堆叠在第9行第2列中的所有先前小部件之上。最终,这会导致程序崩溃。我很惊讶它导致你的程序如此迅速地失败,但那就是重点。
我的建议是从一个简单的例子重新开始,除了每秒更新一个标签之外什么都不做。让它工作,以便您了解基本机制。然后,一旦它工作,您可以添加从串行端口读取的代码。
答案 1 :(得分:0)
我建议您重新开始使用以下代码吗?如果需要,您可以回到Python 2,但是您的程序已被重写为使用Python 3,并且已设计为使用tkinter
能够使用after
方法安排未来事件。希望您会发现代码更容易理解。
import collections
import timeit
import tkinter
def main():
root = Application()
root.setup()
root.mainloop()
class Application(tkinter.Tk):
def setup(self):
mf = self.__middle_frame = tkinter.Frame(self)
self.__middle_frame.grid()
bf = self.__bot_frame = tkinter.Frame(self)
self.__bot_frame.grid()
self.__port_set = False
self.__chip_number = 0
self.__chip_pass_num = 0
self.__chip_fail_num = 0
self.__chip_yield_num = 0
self.__stop = True
self.__widgets = collections.OrderedDict((
('COT', 'Continuity Test'), ('CHE', 'Chip Erase'),
('ERT', 'Erase Test'), ('WRT', 'Write Test'),
('WIRT', 'Wire Reading Test'), ('WIT', 'Wire Reading Test'),
('WRAT', 'Write All Test'), ('DO', 'Done')))
for row, (key, value) in enumerate(self.__widgets.items()):
label = tkinter.Label(mf, text=value+':')
label.grid(row=row, column=0, sticky=tkinter.E)
canvas = tkinter.Canvas(mf, bg='yellow', width=10, height=10)
canvas.grid(row=row, column=1)
self.__widgets[key] = label, canvas
self.__cn = tkinter.Label(mf, text='Chip Number:')
self.__cn.grid(row=8, column=0, sticky=tkinter.E)
self.__display = tkinter.Label(mf)
self.__display.grid(row=8, column=1, sticky=tkinter.E)
self.__button = tkinter.Button(bf, text='START',
command=self.__start_pre)
self.__button.grid(sticky=tkinter.E)
def __start_pre(self):
self.__button['state'] = tkinter.DISABLED
self.__start_button(0)
def __start_button(self, count):
if count < 100:
self.__chip_number += 1
self.__display['text'] = str(self.__chip_number)
self.__widgets['DO'][1]['bg'] = 'yellow'
start_time = timeit.default_timer()
print('Still Working:', self.__chip_number)
self.after(500, self.__end_button, count)
else:
self.__button['state'] = tkinter.NORMAL
def __end_button(self, count):
self.__widgets['DO'][1]['bg'] = 'green'
self.after(500, self.__start_button, count + 1)
if __name__ == '__main__':
main()