0

What is best way to get this work? Script hanging at showinfo:

from tkinter import *
from tkinter.messagebox import *
from threading import Timer

def timerDone():
    showinfo('Alert','Alert')

window = Tk()
mainTimer = Timer(3, timerDone)
mainTimer.start()

window.mainloop()

I use Python 3. Is there is a way to get it work without Queue or additional imports?

I don't use "after" method because Timer can be stoped or changed - I have a lot of timers with dynamically changeable interval and this is very inconvenient.

hddn
  • 5
  • 3
  • 1
    Have you tried implementing this? http://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.after-method – atlasologist Jul 29 '14 at 11:11
  • Yes, but i need timer to be able stop it before or change. – hddn Jul 29 '14 at 11:21
  • you can cancel something started by `after` with the [after_cancel](http://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.after_cancel-method) method. [Here's one answer](http://stackoverflow.com/a/9777453/7432) that shows how to do it. – Bryan Oakley Jul 29 '14 at 11:26
  • Thank you. Anyway, is there is a way to do this without `after` and etc? I have a lot of timers with dynamically changeable interval and this is very inconvenient. – hddn Jul 29 '14 at 11:55
  • Possible duplicate of [python tkinter with threading causing crash](https://stackoverflow.com/questions/14168346/python-tkinter-with-threading-causing-crash) – ivan_pozdeev Apr 18 '18 at 12:40

1 Answers1

2

As discussed here: python tkinter with threading causing crash

Tkinter is not thread safe; you cannot access Tkinter widgets from anywhere but the main thread.

You should remove the Timer instantiation. Tk has its own tool for scheduling events called the after method.

from tkinter import *
from tkinter.messagebox import *

def timerDone(window):
    showinfo('Alert','Alert')
    window.destroy()

window = Tk()
window.after(3000,lambda:timerDone(window))
window.mainloop()

This is the same script implemented using after. I also added a window.destroy() call to break the mainloop.

There are a couple of solutions to your problem. The simplest is to use the after_cancel method to stop a callback from being executed. Its worth also noting that after events are bound to a widget, so if the widget that owns the after is destroyed, the callback will never be executed.

Community
  • 1
  • 1
ebarr
  • 7,704
  • 1
  • 29
  • 40
  • Thank you. Really there is no other option exept `after`? I really enjoy working with a timer, especially when i have many of them (10-15). Very conveniently control them with `isAlive, finished, function, interval` etc. – hddn Jul 29 '14 at 11:45
  • There are lots of options. For instance you could create timer instances that set events and then have after callbacks to check their states. Basically if you want to use Timers, you will have to use them together with after calls. – ebarr Jul 30 '14 at 00:06