Issue
I tried to figure out how the event queue is processed in tkinter. I found this link once and since I played around but I observed different behavior.
The top of my code is:
import tkinter as tk
from tkinter import ttk
def p_trace(*tkargs):
return print('trace', var.get())
def p_binding(event):
return print(event.type,var.get())
root = tk.Tk()
var = tk.IntVar(root)
var.trace_add('write',p_trace)
The p_after
is on different location in the print order by using 0 ms.
def after_done():
return print('after',var.get())
check3= ttk.Checkbutton(root,text='event/trace/after',
command=lambda t=0:root.after(t,after_done),
variable=var)
check3.bind('<Button-1>',p_binding)
check3.pack()
The expected order would be for me, based on the link I have found, like this:
- ButtonPress 0
- trace 1
- after 1
- ButtonPress 1
- trace 0
- after 0
But if you click on the button, like gambling, the actual order can be sometimes:
- ButtonPress 1
- trace 0
- ButtonPress 0
- after 0
- trace 1
- after 1
The p_pseudo
should be always on top via when='head'
but it isn't, never:
def p_pseudo(*tkargs):
return print('pseudo',var.get())
check2= ttk.Checkbutton(root,text='event/trace/pseudo',
command=lambda:check2.event_generate('<<pseudo_event>>',when='head'),
variable=var)
check2.bind('<Button-1>',p_binding)
check2.bind('<<pseudo_event>>',p_pseudo)
check2.pack()
The p_after
with after_idle
gives also strange output.
def after_done():
return print('after',var.get())
check4= ttk.Checkbutton(root,text='event/trace/after',
command=lambda:root.after_idle(after_done),
variable=var)
check4.bind('<Button-1>',p_binding)
check4.pack()
This seems like arbitrary behavior and makes it in some of my cases hard to have the right order of events. I need to slow my program down for secure execution. Is it possible to determinate the event queue of tkinter or its not likely?
Solution
To order the Event Queue of tkinter one have either to bypass all events and trigger them in the prefered order. Or works with a specific type of event, means a sepecific flag. Otherwise tkinters Notifier will process the order of events like below. Another solution for people of tcl knowlege would be to write a own Notifier like described here.
Tcl_Notifier
|
|
|
Tcl_DoOneEvent ------+----> get_first/oldest from Tcl_WINDOW_EVENTS (processes msg of WM)
^ |
| +----> get_first/oldest from Tcl_FILE_EVENTS (tk.Tk.createfilehandler)
| |
| +----> get_first/oldest from Tcl_TIMER_EVENTS (after)
| |
| +----> get_first/oldest from Tcl_IDLE_EVENTS (after_idle)
| |
| +----> get_first/oldest from Other event sources (virtual events)
| |
| +----> Tcl_SetTimer(time|maxtime) ----> Tcl_WaitForEvent ----+
| |
+-------------------------------------------------------------------------------+
BTW, there are some additional conclusions:
- If after maxtime the command Tcl_DoOneEvent cant be invoked there will be a runtime error.
Answered By - Thingamabobs
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.