flazzo
flazzo

Reputation: 253

TKinter: No response when capturing key presses

I may have a fundamental misunderstanding of how capturing key presses works. I've got a basic key press and an effect all set up, but when I attempt to do the same thing in a larger script, it has no effect. For instance, this first program works just fine. I press the spacebar, and the window closes.

import Tkinter as tk
class ExampleApp(tk.Tk):
    def __init__(self):
        def pressSpace(event):
            self.destroy()

        tk.Tk.__init__(self)
        w, h = self.winfo_screenwidth(), self.winfo_screenheight()
        self.geometry("%dx%d+0+0" % (w, h))
        self.bind("<space>", pressSpace)
if __name__ == "__main__":
    app = ExampleApp()
    app.mainloop()

But this second one does not appear to do anything when space is pressed.

#Program has been greatly simplified without affecting the outcome
import Tkinter as tk
class ExampleApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)

        # make program fullscreen
        w, h = self.winfo_screenwidth(), self.winfo_screenheight()
        self.geometry("%dx%d+0+0" % (w, h))

        self.label = tk.Label(self)
        self.label.pack()
        self.remaining = 0
        self.countdown(15)

    def countdown(self, remaining = None):
        paused = 0
        def pressSpace(event):
            if(paused == 0):
                paused = 1
            else:
                paused = 0

        #bind spacebar to pause the timer
        self.bind(self, "<space>", pressSpace)

        if remaining is not None:
            self.remaining = remaining

        if self.remaining <= 0:
            #Time has expired. Players lose
            self.label.configure(text="TIME!", fg='black', bg='brown')
        else:
            #There is still time on the clock. This cuts the time into readable chunks
            self.label.configure(text= str(self.remaining) + ' - Paused = ' + str(paused))
            if(paused == 0):
                #Check if the timer is toggled to pause
                self.remaining = self.remaining - 1
                self.after(1000, self.countdown)
if __name__ == "__main__":
    app = ExampleApp()
    app.mainloop()

I don't get it. The program seems functionally similar and everything is contained in the same function, but the variable 'paused' doesn't seem to change at all and the timer does not stop.

I'm scared. Have I strayed from The Path?

Upvotes: 1

Views: 238

Answers (1)

Anand S Kumar
Anand S Kumar

Reputation: 90899

Lots of issues in your code -

  1. Your binding seems to be wrong -

    self.bind(self, "<space>", pressSpace)
    

    Not sure why you are sending self again. You should be doing -

    self.bind("<space>", pressSpace)
    
  2. In your function - pressSpace() - since you are setting paused=0 or paused=1 , the paused is treated as local variable to that function, so you would get an error - UnboundLocalError: local variable 'paused' referenced before assignment . Instead , I would adivce you to set paused as an instance variable on self and use it.

  3. Secondly, even if binding becomes correct, in each call to countdown , you are changing paused back to 0. For this you should move the binding and setting paused to 0 logic to __init__() . and then when the application is unpaused you would need to re-start the countdown.

Code that works -

import Tkinter as tk
class ExampleApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)

        # make program fullscreen
        w, h = self.winfo_screenwidth(), self.winfo_screenheight()
        self.geometry("%dx%d+0+0" % (w, h))

        self.label = tk.Label(self)
        self.label.pack()
        self.remaining = 0
        self.paused = 0
        def pressSpace(event):
            if(self.paused == 0):
                self.paused = 1
            else:
                self.paused = 0
                self.countdown()

        #bind spacebar to pause the timer
        self.bind("<space>", pressSpace)
        self.countdown(15)

    def countdown(self, remaining = None):
        if remaining is not None:
            self.remaining = remaining

        if self.remaining <= 0:
            #Time has expired. Players lose
            self.label.configure(text="TIME!", fg='black', bg='brown')
        else:
            #There is still time on the clock. This cuts the time into readable chunks
            self.label.configure(text= str(self.remaining) + ' - Paused = ' + str(self.paused))
            if(self.paused == 0):
                #Check if the timer is toggled to pause
                self.remaining = self.remaining - 1
                self.after(1000, self.countdown)
if __name__ == "__main__":
    app = ExampleApp()
    app.mainloop()

Upvotes: 2

Related Questions