我使用滑块来更新可视化,但每次移动滑块拇指时都会发送命令 updateValue,即使对于中间值也是如此。
相反,我只想在释放鼠标按钮并且交互完成时触发它。
self.slider = tk.Scale(self.leftFrame, from_=0, to=256, orient=tk.HORIZONTAL, command=updateValue)
如何在交互结束时仅触发该功能一次?
这是一个相当古老的问题,但如果有人偶然发现这个特定问题,只需使用bind()函数和“ButtonRelease-1”事件,如下所示:
import Tkinter as tk
class App:
def __init__(self):
self.root = tk.Tk()
self.slider = tk.Scale(self.root, from_=0, to=256,
orient="horizontal")
self.slider.bind("<ButtonRelease-1>", self.updateValue)
self.slider.pack()
self.root.mainloop()
def updateValue(self, event):
print self.slider.get()
app=App()
希望这对任何人都有帮助!
你不能。
您可以做的是让您的命令使用“after”在短时间内延迟任何实际工作。每次调用命令时,取消任何待处理的工作并重新安排工作。根据您的实际要求,半秒的延迟可能就足够了。
另一种选择是不使用内置命令功能,而是使用自定义绑定。要做到完全正确可能需要做很多工作,但如果您确实需要细粒度的控制,您可以做到。不要忘记,除了鼠标之外,还可以使用键盘与小部件交互。
这是一个简短的示例,展示了如何安排在半秒内完成的工作:
import Tkinter as tk
#create window & frames
class App:
def __init__(self):
self.root = tk.Tk()
self._job = None
self.slider = tk.Scale(self.root, from_=0, to=256,
orient="horizontal",
command=self.updateValue)
self.slider.pack()
self.root.mainloop()
def updateValue(self, event):
if self._job:
self.root.after_cancel(self._job)
self._job = self.root.after(500, self._do_something)
def _do_something(self):
self._job = None
print "new value:", self.slider.get()
app=App()
带有标签和值的去抖 tk 比例
import tkinter as tk
from tkinter import ttk
class tk_scale_debounced(ttk.Frame):
"""
scale with after_change event
aka: debounced scale
example:
def after_change(key, value):
print(key, value)
root = tk.Tk()
s = tk_scale_debounced(root, "some label", after_change, "x", from_=-10, to=10)
s.pack()
"""
# current value
value = None
# debounce timer for keyboard input
_change_key_timer = None
def __init__(self, parent, label, after_change, key=None, **scale_kwargs):
"""
example scale_kwargs:
from_=-10, to=10, orient='horizontal'
"""
super().__init__(parent)
self._after_change = after_change
self._label = label
self._key = key or label
self.value = tk.DoubleVar()
self.columnconfigure(0, weight=2)
self.columnconfigure(1, weight=1)
self.columnconfigure(2, weight=100)
# label
self._scale_label = ttk.Label(self, text=self._label)
self._scale_label.grid(column=0, row=0, sticky='w')
# value
self._value_label = ttk.Label(self, text=self._format_value())
self._value_label.grid(column=1, row=0, sticky='w')
# scale
self._scale = ttk.Scale(self, command=self._scale_change_live, variable=self.value, **scale_kwargs)
self._scale.grid(column=2, row=0, columnspan=4, sticky='we')
# mouse
self._scale.bind("<ButtonRelease-1>", self._scale_change_done)
# keyboard
self._scale.bind("<KeyRelease>", self._scale_change_key)
def _format_value(self):
return '{: .2f}'.format(self.value.get())
def _scale_change_live(self, event):
self._value_label.configure(text=self._format_value())
def _scale_change_done(self, event=None):
self._after_change(self._key, self.value.get())
def _scale_change_key(self, event):
if self._change_key_timer:
self.after_cancel(self._change_key_timer)
t = 1000
self._change_key_timer = self.after(t, self._scale_change_done)