How to limit the number of events generated by widget

前端 未结 1 1031
走了就别回头了
走了就别回头了 2020-12-11 12:15

I\'m using a spinbox to control the size of fonts in real time, for a zooming effect. A spinbox widget can generate a lot of events. As long as you hold down a direction key

相关标签:
1条回答
  • 2020-12-11 12:44

    I used similar solutions for both kinds of spinboxes but the implementation is a bit different since they don't use the same events. The idea is to create a Spinbox class with an _increment_lock attribute which is set to True when the Spinbox is incremented and after a delay is set back to False. Then, the events that increment the spinbox are bound to a method that checks _increment_lock before actually performing the increment. The principle is the same for the decrement.

    For the tk.Spinbox, I used the bindings to the <Up> and <Down> arrows to implement the above solution while I used the bindings to <<Increment>> and <<Decrement>>.

    Here is the code:

    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()
    
    0 讨论(0)
提交回复
热议问题