Ticket UUID: | ce6b428620dd89bc46786654e3aa1d62d74d3fc8 | |||
Title: | <<Increment>> event is endlessly triggered once messagebox closes | |||
Type: | Bug | Version: | TkVersion 8.6 | |
Submitter: | GOLosinas | Created on: | 2022-02-10 02:40:25 | |
Subsystem: | 02. Event Loops | Assigned To: | fvogel | |
Priority: | 5 Medium | Severity: | Important | |
Status: | Closed | Last Modified: | 2022-02-25 23:25:20 | |
Resolution: | Fixed | Closed By: | fvogel | |
Closed on: | 2022-02-25 23:25:20 | |||
Description: |
I am using a ttk.Spinbox to capture some number and I want to display a messagebox once the value in the spinbox reaches the limit. I bound the spinbox to the <code> <<Increment>> </code> event to perform a check, and display the message but the event is endlessly triggered once you close the messagebox. I made a small application to illustrate the issue. class App(Tk): def __init__(self): super().__init__() self.title('Sample') self.geometry('300x100') Selector(self).pack() class Selector(ttk.Frame): def __init__(self, container): super().__init__(container) self.max_length = 10 self.input = IntVar(0) self.check_length_calls = 0 self.label = ttk.Label(self, text="Quantity: ").pack() self.spinbox = ttk.Spinbox(self, from_=0, to=10, textvariable=self.input) self.spinbox.pack() self.spinbox.bind('<<Increment>>', lambda e: self.check_length(e)) ttk.Button(self, text="print func calls", command= self.print_check_length_calls).pack() def check_length(self, e): self.check_length_calls += 1 if str(self.spinbox) != str(self.focus_get()): return if self.input.get() == self.max_length: messagebox.showwarning("Max length reached", "Too long!") self.focus_set() def print_check_length_calls(self): print(self.check_length_calls) if __name__ == "__main__": app = App() app.mainloop() | |||
User Comments: |
fvogel added on 2022-02-25 23:25:20:
Merged in core-8-6-branch and trunk (of Tk). fvogel added on 2022-02-18 21:22:34: The fix obviously is in the Tk repository: https://core.tcl-lang.org/tk/info/fb9a3632373e63e3 The present ticket should have been opened there btw. fvogel added on 2022-02-18 21:20:20: The problem is due to the following. When clicking the up arrow of the spinbox, an <<Increment>> virtual event is generated from ttk::spinbox::Press. This event is repeatedly generated:
ttk::Repeatedly runs its provided script ( This re-scheduling repeats until the up arrow button is released (mouse button up), at which time ttk::spinbox::Release gets called, which calls ttk::CancelRepeat to, well... cancel the repeat! This implementation allows to increment repeatedly the spinbox value by pressing and maintaining the up arrow down. Incrementation starts when pushing down the mouse button on the up arrow, and it stops when releasing the mouse button. Now, with this implementation, when the script bound to The fix therefore is to swap the order of script execution and repetition scheduling, see [fb9a363237]. fvogel added on 2022-02-18 20:59:00: Trimmed down script allowing to reproduce the issue on Windows (at least): package require Tk pack [ttk::spinbox .s] bind .s <<Increment>> {tk_messageBox -message "Message!"} # and click on the up arrow fvogel added on 2022-02-16 10:37:24: Christopher's script below triggers the reported problem on Windows 10, with Tk 8.6.9, or core-8-6-branch, or main. chrstphrchvz added on 2022-02-16 09:58:59: The reporter may likely need to provide more information; what is the output of Tk().getvar('tk_patchLevel') and Tk().tk.eval('tk windowingsystem')? I ran the Tkinter example (need to do from tkinter import *; from tkinter import ttk, messagebox first) and did not observe the reporter's issue for Tcl/Tk 8.6.12 on X11. However if I tweak Francois' Tcl example to resemble the reporter's Tkinter a little more (no separate toplevel, show a messagebox, focus on the spinbox afterward): package require Tk set max_length 10 set check_length_calls 0 set input 0 proc check_length {} { global check_length_calls max_length incr check_length_calls if {[focus] ne ".s"} {return} if {[.s get] == $max_length} { tk_messageBox -title "Max length reached" -message "Too long!" -icon warning focus .s } } wm geometry . 300x100 ttk::label .l -text "Quantity: " ttk::spinbox .s -from 0 -to 10 -textvariable input bind .s <<Increment>> {check_length} ttk::button .b -text "Print fun calls" -command {puts $check_length_calls} pack .l .s .b …then I do observe that every time the messagebox is dismissed, another will appear shortly. But I wonder if this behavior is intentional/as documentation would suggest, and just something Tk programs need to beware. fvogel added on 2022-02-10 07:21:58: Thank you for your report. Please note that this is the Tcl tracker, not the Tk tracker. If the issue gets confirmed this ticket should be closed and reopened in the Tk tracker. Furthermore your code seems to be in Python. What I believe is the equivalent Tcl/Tk code is as follows: package require Tk set max_length 10 set check_length_calls 0 set input 0 proc check_length {} { global check_length_calls max_length incr check_length_calls if {[focus] ne ".t.s"} {return} if {[.t.s get] == $max_length} { puts "Too long" } } toplevel .t wm geometry .t 300x100 ttk::label .t.l -text "Quantity: " ttk::spinbox .t.s -from 0 -to 10 -textvariable input bind .t.s <<Increment>> {check_length} ttk::button .t.b -text "Print fun calls" -command {puts $check_length_calls} pack .t.l .t.s .t.b But with this code I fail to reproduce the problem you describe. |
