python - Tkinter - 事件队列和事件顺序
问题描述
我试图弄清楚事件队列是如何在 tkinter 中处理的。我发现这个链接一次,因为我玩过,但我观察到不同的行为。
我的代码的顶部是:
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)
p_after
使用 0 毫秒位于打印顺序中的不同位置。
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()
根据我找到的链接,预期的订单对我来说是这样的:
- 按钮按下 0
- 迹线 1
- 1 之后
- 按钮按下 1
- 跟踪 0
- 0后
但是如果你点击按钮,比如赌博,实际的顺序有时可能是:
- 按钮按下 1
- 跟踪 0
- 按钮按下 0
- 0后
- 迹线 1
- 1 之后
p_pseudo
应该总是在顶部,但when='head'
它不是,永远不会:
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()
p_after
withafter_idle
也给出了奇怪的输出。
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()
这似乎是任意行为,并且在我的某些情况下很难拥有正确的事件顺序。我需要放慢我的程序以确保安全执行。是否可以确定 tkinter 的事件队列或不可能?
解决方案
要订购 tkinter 的事件队列,必须绕过所有事件并以首选顺序触发它们。或者与特定类型的事件一起使用,意味着一个特定的标志。否则 tkinters Notifier将处理如下事件的顺序。tcl 知识的人的另一种解决方案是编写一个自己的通知程序,如此处所述。
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 ----+
| |
+-------------------------------------------------------------------------------+
顺便说一句,还有一些额外的结论:
- 如果在 maxtime 之后无法调用命令 Tcl_DoOneEvent,则会出现运行时错误。
推荐阅读
- c - 有没有办法阻止我的程序打印重复项?
- twilio - 进行更改后如何设置 Twilio Flex WebChat?
- reactjs - 我们是否需要使用 React Native 0.60 运行 `pod install`?
- android - 当我们转到其他图形时如何在抽屉中显示汉堡包(具有多模块的导航组件)
- node.js - Puppeteer 和 jnode 多个异步调用在同一时间结束时返回相同的结果
- firebase - 运行连续的 Firestore 查询时出现虚假的 MaxListenersExceededWarning EventEmitter 内存泄漏
- java - JavaFX on ActionEvent 动态添加/删除节点
- uiscrollview - 在 SwiftUI ScrollView 中获取和设置内容的位置
- java - 在java中使用Selenium自动将图像上传到instagram
- java - 如何在 while 循环中使用扫描仪