我正在tkinter中设计应用程序,我需要每秒一行一行地读取文件,并每秒查看一次小部件上的结果。问题是我的程序正在读取整个文件,并且仅在此更新后才读取Gui。
class Gui(Frame):
def __init__(self, master):
super(Gui, self).__init__()
self.master = master
# ... here are my tkinter widgets
self.ser = None
self.start_update()
def start_update(self):
if self.ser is None:
self.ser = open("serial.txt") # open only once
self.updater()
def updater(self):
while True:
self.raw_line = self.ser.readline()
if self.raw_line:
# here I update labels with .configure() method
self.after(1000, self.updater)
else:
print('Probably end of file')
self.ser.close()
self.ser = None # can open again
root = Tk()
gui = Gui(root)
root.mainloop()
答案很简单:在处理GUI的主线程中有一个无限循环。结果,GUI挂起,直到循环中断。
这是一个简单的解决方法:
class MainWindow(Frame):
def __init__(self, master=None):
super().__init__(master)
self.file = None
self.update_from_file()
self.master.protocol('WM_DELETE_WINDOW', self.on_close)
def open_file(self, filename="serial.txt"):
if self.file is not None:
self.file = open(filename)
def update_from_file(self):
line = self.file.readline()
if line:
# update the widgets
# reminder : when applicable, use tkinter variables
# as they are easier to handle than manually updating with .config()
self.after(1000, self.update_from_file)
def on_close(self):
self.file.close()
self.file = None # can open again
root = Tk()
gui = MainWindow(root)
root.mainloop()
这样,update_from_file方法在处理时不会挂起主线程。
如果需要额外的CPU余量,另一个有效的方法是用threading
创建一个单独的线程,并使用该线程从文件中读取。由于两个线程是分开的,因此也不会挂起tkinter线程。但是,如果您打算在打开文件时进行编辑,则必须谨慎对待竞争条件。