Giga Chad Coding
Giga Chad Coding

Reputation: 198

Tkinter Event Handler Unable to See Global Variables

Whenever the on_click event handler is invoked for my button its method doesn't acknowledge the existence of my global variable.

What is occurring to cause this, and how do/can I access my global variables inside the event handler?

I've already tried passing the value of the global variable into the method,

from pynput.mouse import Button, Controller
from pynput import mouse

import tkinter as tk
import sys

controller = Controller()
recordings = []
is_recording = False
listener = None
top = tk.Tk()


class Recording:
    def __init__(self):
        self.actions = []
        self.key_bind_code = -1

    def add_action(self):
        self.actions.append(controller.position)

    def play(self):
        for action in actions:
            do_action(action)


def on_click(recording):
    recording.add_action()

def start_recording():
    r = Recording()
    recordings.append(r)
    listener = mouse.Listener(on_click=on_click(r))
    listener.start()

def stop_recording():
    listener.stop()

def handle_recording():
    print("Recording: " + str(is_recording))
    if is_recording:
        stop_recording()
        is_recording = False
    else:
        start_recording()
        is_recording = True


button = tk.Button(top, text="Record", command=handle_recording)
button.pack()

top.mainloop()

When the handler is invoked, this is the message I receive.

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\pdiddy\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
    return self.func(*args)
  File "repeat.py", line 60, in handle_recording
    print("Recording: " + str(is_recording))
UnboundLocalError: local variable 'is_recording' referenced before assignment

Upvotes: 1

Views: 1753

Answers (1)

martineau
martineau

Reputation: 123473

To make is_recording not be considered a local variable in the handle_recording() function, you must declare that it isn't one by adding a global is_recording statement to the beginning of the function. Like this:

def handle_recording():
    global is_recording  # ADD THIS LINE.
    print("Recording: " + str(is_recording))
    if is_recording:
        stop_recording()
        is_recording = False
    else:
        start_recording()
        is_recording = True

While one can read the value of an existing global variable that hasn't been declared global — because of the way Python looks up values — to change the value of one however, you must explicitly declare it as a global. By convention the recommended place to do that is at the very beginning of the block of code within which it's being manipulated (the function here).

Upvotes: 2

Related Questions