Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python tkinter binding: How to prevent double events

I have a python program which uses tkinter and key bindings. The program calls an external program and then asks, what to do with it, expecting n-key for "no" or y-key for "yes". The problem: If I press the allowed key twice, the second key is stored and processed later on - thus for the wrong question.

import tkinter as tk
import time

class App:
    counter = 0

    def __init__(self, master): # Constructor
        # build GUI
        self.label = tk.Label(text="Press <space>", width=40)
        self.label.grid(row=1, column=1, sticky='w')

        # bind keys to buttons
        master.bind('<Key-space>', self.keyPressed)
        pass # __init__


    def keyPressed(self, event):
        print("Step 1")
        self.counter = self.counter + 1
        self.label.configure(text = str(self.counter))
        self.label.update()
        time.sleep(3)
        print("Step  2")
        pass # Key1Pressed
# End of class App

root = tk.Tk()
root.option_add('*font', ('Arial', 11, 'bold'))
# root.attributes("-toolwindow", 1)

posX = root.winfo_screenwidth() - 500
posY = 30
root.geometry("+%d+%d" % (posX, posY))

root.title("Bind tester")
display = App(root)
root.mainloop()

In the code snippet above I replaced the external program by sleep() and the key binding for the spacebar. If the python3 skript is started and space is pressed two times within the sleep period, I see outputs in the terminal like:

Step 1
Step  2
Step 1
Step  2

I would like to ignore any key event, that was raised during the sleep routine. So next I tried to use a semaphore, but this was also not successful. The problem might be more complex, because if I press space three times within the sleep period, I'll get the following result:

Step 1
Step  2
Step 1
Step 1
Step  2
Step  2

Looks as if the function keypressed is called multiple times in parallel. Is there a possibility to clear the event queue before accepting new events?

like image 700
DirkS Avatar asked Sep 01 '25 18:09

DirkS


1 Answers

Probably the time.sleep method is messing with Tkinter mainloop. You should use the 'after' method from Tkinter module.

http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/universal.html

If you do not pass a callback argument, this method waits delay_ms milliseconds, as in the .sleep() function of the standard Python time module.

Check this post for an example:

Python time.sleep