I recently started testing out Tkinter to make simple apps that can hook into an API and give a user a sampling of data from that API. One thing I wanted was for this window to refresh occasionally, updating the information so that it's never too far out of date.
However, it seems that the tkinter window is crashing regularly. No errors or messages are returned, it just becomes unresponsive at erratic times. Adding large numbers of widgets makes the crash happen sooner, but with different numbers of widgets it seems to happen eventually regardless.
To make it autorefresh at intervals, I set up a thread that would call the tkinter App's redraw
method. From my research I know that tkinter isn't thread safe, but I thought that wouldn't be an issue when I have just the one thread every 30 seconds calling a redraw method that takes a moment to run.
Here's a minimal version of my app that will crash after a few attempted redraws. My actual data has only about 15 widgets and crashes eventually, but raising the number to very high values makes the crashes happen earlier and makes it easier to test with.
from Tkinter import *
from threading import Thread, Event
REFRESH_INTERVAL = 30
class App(Frame):
names = ["test"] * 50
def __init__(self, master):
Frame.__init__(self, master)
self.frame = master
self.table = None
self.redraw()
def redraw(self):
if self.table:
self.table.destroy()
new_frame = Frame(self.frame)
new_frame.pack()
self.table = new_frame
for code in self.names:
label = Label(new_frame, text=code)
label.pack()
class Refresher(Thread):
def __init__(self, event, app):
Thread.__init__(self)
self.stopped = event
self.app = app
def run(self):
while not self.stopped.wait(REFRESH_INTERVAL):
print("Refreshing...")
self.app.redraw()
def main():
root = Tk()
app = App(root)
app.pack(side=TOP, fill="both", expand=True)
stop_flag = Event()
refresher = Refresher(stop_flag, app)
refresher.start()
root.mainloop()
stop_flag.set()
if __name__ == "__main__":
main()