我正在使用一个旋转框来实时控制字体的大小,以实现缩放效果。旋转框小部件可以生成许多事件。只要您按住键盘上的方向键或单击并按住方向小部件箭头图标之一,旋转框就会生成事件。 问题是我收到太多事件,这导致缩放效果挂起。我已经设置了一个演示,使用两个不同的旋转框(tk.Spinbox 和 ttk.Spinbox)展示了这一点。使用 tk.Spinbox,您可以使用“repeatdelay 和 repeatinterval”限制速率,这确实有效,但只有当您单击旋转框中的一个箭头按钮时才有效。但是,如果您按下向上或向下键,“repeatdelay 和 repeatinterval”不起作用。至于 ttk.Spinbox,它不接受参数“repeatdelay 和 repeatinterval”,因此它对它没有影响。我如何限制这两种类型的旋转框的重复率?
import tkinter as tk import tkinter.ttk as ttk class App(tk.Tk): def __init__(self): super().__init__() self.rowconfigure(990, weight=1) self.columnconfigure(0, weight=1) self.title('Timed Events Demo') self.geometry('420x200+20+20') tk_spn = tk.Spinbox( self, value=0, from_=0, to=1000, repeatdelay=500, repeatinterval=500, values=list(range(0, 1000)) ) tk_spn.grid(row=0, pady=5) tk_spn = ttk.Spinbox( self, from_=0, to=1000, value=0, values=list(range(0, 1000)) ) tk_spn.grid(row=1, pady=5) self.cnt = 0 def test(e): print(self.cnt, e) tk_spn.bind('<<Increment>>', test) def main(): app = App() app.mainloop() if __name__ == '__main__': main()
我对这两种类型的旋转框使用了类似的解决方案,但由于它们使用的事件不同,因此实现方式略有不同。这个想法是创建一个 Spinbox 类,该类具有一个_increment_lock属性,当 Spinbox 增加时,该属性设置为True,并在延迟后重新设置为False。然后,将增加旋转框的事件绑定到在实际执行增加之前进行检查的方法_increment_lock。减少的原理相同。
_increment_lock
True
False
对于,我使用到和箭头的tk.Spinbox绑定来实现上述解决方案,而我使用到和 的绑定。<Up>``<Down>``<<Increment>>``<<Decrement>>
tk.Spinbox
<Up>``<Down>``<<Increment>>``<<Decrement>>
以下是代码:
import tkinter as tk import tkinter.ttk as ttk class MySpinbox(tk.Spinbox): def __init__(self, master=None, delay=500, **kwargs): kwargs.setdefault('repeatdelay', delay) kwargs.setdefault('repeatinterval', delay) tk.Spinbox.__init__(self, master, **kwargs) self.delay = delay # repeatdelay in ms self.bind('<Up>', self._on_increment) self.bind('<Down>', self._on_decrement) self._increment_lock = False self._decrement_lock = False def _unlock_increment(self): self._increment_lock = False def _on_increment(self, event): if self._increment_lock: return "break" # stop the increment else: self._increment_lock = True self.after(self.delay, self._unlock_increment) def _unlock_decrement(self): self._decrement_lock = False def _on_decrement(self, event): if self._decrement_lock: return "break" # stop the increment else: self._decrement_lock = True self.after(self.delay, self._unlock_decrement) class MyTtkSpinbox(ttk.Spinbox): def __init__(self, master=None, delay=500, **kwargs): ttk.Spinbox.__init__(self, master, **kwargs) self.delay = delay # repeatdelay in ms self.bind('<<Increment>>', self._on_increment) self.bind('<<Decrement>>', self._on_decrement) self._increment_lock = False self._decrement_lock = False def _unlock_increment(self): self._increment_lock = False def _on_increment(self, event): if self._increment_lock: return "break" # stop the increment else: # generate a virtual event corresponding to when the spinbox # is actually incremented self.event_generate('<<ActualIncrement>>') self._increment_lock = True self.after(self.delay, self._unlock_increment) def _unlock_decrement(self): self._decrement_lock = False def _on_decrement(self, event): if self._decrement_lock: return "break" # stop the increment else: # generate a virtual event corresponding to when the spinbox # is actually decremented self.event_generate('<<ActualDecrement>>') self._decrement_lock = True self.after(self.delay, self._unlock_decrement) class App(tk.Tk): def __init__(self): super().__init__() self.rowconfigure(990, weight=1) self.columnconfigure(0, weight=1) self.title('Timed Events Demo') self.geometry('420x200+20+20') tk_spn1 = MySpinbox(self, value=0, values=list(range(0, 1000))) tk_spn1.grid(row=0, pady=5) tk_spn2 = MyTtkSpinbox(self, from_=0, to=1000) tk_spn2.grid(row=1, pady=5) def test(e): print(e) tk_spn2.bind('<<ActualIncrement>>', test) if __name__ == '__main__': app = App() app.mainloop()