I am trying to build a GUI with Tkinter and use it to control my Raspberry Pi robot. With some help, I managed to get the functionality of the buttons when being pressed and held down but I am struggling with the function that will allow me to do things with the switch button.
here is a quick snippet of the Tkinter code:
# LED Lights
self.led_switch = customtkinter.CTkSwitch(master=self.lights_control, text="LED",
command=lambda: self.led_switch())
self.led_switch.grid(row=0, column=1, pady=10, padx=20, sticky="n")
and here is the function I'm trying to implement:
is_on = True
def led_switch(self, event):
global is_on
if is_on:
print("It is on")
#is_on = False
else:
print("It is off")
#is_on = True
This doesn't seem to work since I'm getting the error message:
self.led_switch = customtkinter.CTkSwitch(master=self.lights_control, text="LED", command=lambda: self.led_switch())
TypeError: 'CTkSwitch' object is not callable`.
here is the full code if that helps:
import tkinter
import tkinter.messagebox
import customtkinter
# Setting up theme
customtkinter.set_appearance_mode("Dark") # Modes: "System" (standard), "Dark", "Light"
customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue"
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
# configure window
self.title("Cool Blue")
self.geometry(f"{1200}x{560}")
# configure grid layout (4x4)
self.grid_columnconfigure(1, weight=1)
self.grid_columnconfigure((2, 3), weight=0)
self.grid_rowconfigure((0, 1, 2, 3, 4), weight=1)
self.bind("<KeyPress>", self.key_pressed)
self.bind("<KeyRelease>", self.key_released)
###################################################################
# create sidebar frame for controls
###################################################################
self.sidebar_frame = customtkinter.CTkFrame(self, width=100)
self.sidebar_frame.grid(row=0, column=0, rowspan=1, padx=(5, 5), pady=(10, 10), sticky="nsew")
self.sidebar_frame.grid_rowconfigure(4, weight=1)
# Setting up grid label
self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="Motion", font=customtkinter.CTkFont(size=15, weight="bold"))
self.logo_label.grid(row=0, column=1, padx=20, pady=(10, 10))
# Setting up W - Forward button
self.button_up = customtkinter.CTkButton(self.sidebar_frame, text="W", height=10, width=10)
self.button_up.grid(row=1, column=1, padx=20, pady=10, ipadx=10, ipady=10)
self.button_up.bind('<ButtonPress-1>', lambda x: self.motion_event_start(x, 'W'))
self.button_up.bind('<ButtonRelease-1>', lambda x: self.motion_event_stop(x, 'W'))
# Setting up S - Backwards buttons
self.button_down = customtkinter.CTkButton(self.sidebar_frame, text="S", height=10, width=10)
self.button_down.grid(row=3, column=1, padx=20, pady=10, ipadx=10, ipady=10)
self.button_down.bind('<ButtonPress-1>', lambda x: self.motion_event_start(x, 'S'))
self.button_down.bind('<ButtonRelease-1>', lambda x: self.motion_event_stop(x, 'S'))
# Setting up A - Left button
self.button_left = customtkinter.CTkButton(self.sidebar_frame, text="A", height=10, width=10)
self.button_left.grid(row=2, column=0, padx=10, pady=10, ipadx=10, ipady=10)
self.button_left.bind('<ButtonPress-1>', lambda x: self.motion_event_start(x, 'A'))
self.button_left.bind('<ButtonRelease-1>', lambda x: self.motion_event_stop(x, 'A'))
# Setting up D - Right button
self.button_right = customtkinter.CTkButton(self.sidebar_frame, text="D", height=10, width=10)
self.button_right.grid(row=2, column=2, padx=10, pady=10, ipadx=10, ipady=10)
self.button_right.bind('<ButtonPress-1>', lambda x: self.motion_event_start(x, 'D'))
self.button_right.bind('<ButtonRelease-1>', lambda x: self.motion_event_stop(x,'D'))
###################################################################
# Create Sidebar for arm control
###################################################################
self.arm_control = customtkinter.CTkFrame(self)
self.arm_control.grid(row=1, column=0, rowspan = 1, padx=(5, 5), pady=(10, 10), sticky="nsew")
self.arm_control.grid_rowconfigure(2, weight=1)
# Setting up grid label
self.arm_label = customtkinter.CTkLabel(self.arm_control, text="Arm", font=customtkinter.CTkFont(size=15, weight="bold"))
self.arm_label.grid(row=0, column=0, padx=20, pady=(10, 10))
self.grip_label = customtkinter.CTkLabel(self.arm_control, text="Grip", font=customtkinter.CTkFont(size=15, weight="bold"))
self.grip_label.grid(row=0, column=1, padx=20, pady=(10, 10))
# Arm Up
self.button_arm_up = customtkinter.CTkButton(self.arm_control, text=" Up ", height=10, width=10)
self.button_arm_up.grid(row=1, column=0, padx=10, pady=10, ipadx=30, ipady=10)
# Arm Down
self.button_arm_down = customtkinter.CTkButton(self.arm_control, text=" Down", height=10, width=10)
self.button_arm_down.grid(row=2, column=0, padx=10, pady=10, ipadx=30, ipady=10)
self.button_grip_open = customtkinter.CTkButton(self.arm_control, text="Open", height=10, width=10)
self.button_grip_open.grid(row=1, column=1, padx=10, pady=10, ipadx=30, ipady=10, sticky="w")
self.button_grip_close = customtkinter.CTkButton(self.arm_control, text="Close", height=10, width=10)
self.button_grip_close.grid(row=2, column=1, padx=10, pady=10, ipadx=30, ipady=10, sticky="w")
###################################################################
# Create Sidebar for grip
###################################################################
self.lights_control = customtkinter.CTkFrame(self)
self.lights_control.grid(row=3, column=0, rowspan = 1, padx=(5, 5), pady=(10, 10), sticky="nsew")
self.lights_control.grid_rowconfigure(1, weight=1)
# LED Lights
self.led_switch = customtkinter.CTkSwitch(master=self.lights_control, text="LED", command=lambda: self.led_switch)
self.led_switch.grid(row=0, column=1, pady=10, padx=20, sticky="n")
# Regular Lights
self.regular_ligths_switch = customtkinter.CTkSwitch(master=self.lights_control, text="Lights", command=lambda: print("switch 1 toggle"))
self.regular_ligths_switch.grid(row=1, column=1, pady=10, padx=20)
# Camera
self.led_switch = customtkinter.CTkSwitch(master=self.lights_control, text="Camera", command=lambda: print("switch 1 toggle"))
self.led_switch.grid(row=2, column=1, pady=10, padx=20, )
# create Video Canvas
self.picam = customtkinter.CTkCanvas(self, width=800, background="gray")
self.picam.grid(row=0, column=1, rowspan=4, padx=(5, 5), pady=(20, 20), sticky="nsew")
self.picam.grid_rowconfigure(4, weight=1)
self.picam_label = customtkinter.CTkLabel(master=self.picam, text="Live Stream", font=customtkinter.CTkFont(size=20, weight="bold"))
self.picam_label.grid(row=0, column=2, columnspan=1, padx=10, pady=10, sticky="")
# create radiobutton frame
self.temperature = customtkinter.CTkFrame(self)
self.temperature.grid(row=0, column=3, rowspan = 1, padx=(5, 5), pady=(10, 10), sticky="n")
self.temperature.grid_rowconfigure(2, weight=1)
self.label_temperature = customtkinter.CTkLabel(master=self.temperature, text="Temperature")
self.label_temperature.grid(row=0, column=2, columnspan=1, padx=10, pady=10, sticky="")
# create checkbox and switch frame
self.pressure = customtkinter.CTkFrame(self)
self.pressure.grid(row=1, column=3, rowspan = 1, padx=(5, 5), pady=(10, 10), sticky="n")
self.pressure.grid_rowconfigure(1, weight=1)
self.label_pressure = customtkinter.CTkLabel(master=self.pressure, text="Pressure")
self.label_pressure.grid(row=0, column=2, columnspan=1, padx=10, pady=10, sticky="")
# create checkbox and switch frame
self.humidity = customtkinter.CTkFrame(self)
self.humidity.grid(row=3, column=3, rowspan = 1, padx=(5, 5), pady=(10, 10), sticky="")
self.humidity.grid_rowconfigure(1, weight=1)
self.label_humidity = customtkinter.CTkLabel(master=self.humidity, text="Humidity")
self.label_humidity.grid(row=0, column=2, columnspan=1, padx=10, pady=10, sticky="")
def key_pressed(self, event):
if event.char in 'wads':
self.motion_event_start(event, event.char.upper())
def key_released(self, event):
if event.char in 'wads':
self.motion_event_stop(event, event.char.upper())
def motion_event_start(self, event, button):
# if button == "W":
# kit1.motor1.throttle = 1
# kit2.motor1.throttle = 1
# elif button == "S":
# kit1.motor1.throttle = -1
# kit2.motor1.throttle = -1
print(f"{button} Pressed")
def motion_event_stop(self, event, button):
print(f"{button} Released")
# kit1.motor1.throttle = 0
# kit2.motor1.throttle = 0
# Switch
is_on = True
def led_switch(self, event):
global is_on
if is_on:
print("It is on")
#is_on = False
else:
print("It is off")
#is_on = True
if __name__ == "__main__":
app = App()
app.mainloop()
Any ideas on what I'm doing wrong here?
CodePudding user response:
There are at least 3 problems with your overall logic.
This line:
self.led_switch=customtkinter.CTkSwitch(master=self.lights_control, text="LED", command=lambda: self.led_switch)
Should be:
self.led_switch=customtkinter.CTkSwitch(master=self.lights_control, text="LED", command=self.led_switch)
This is because lambda is not needed here and your lambda: call was only saving a reference to the function and not actually calling it when triggered.
Next you need to change the function that is receiving the call since you are not explicitly passing an event and it is expecting on.
So change this:
def led_switch(self, event):
global is_on
if is_on:
print("It is on")
is_on = False
else:
print("It is off")
is_on = True
To this:
# You can use event=None or remove event or use another option if needed.
def led_switch(self, event=None):
global is_on
if is_on:
print("It is on")
is_on = False
else:
print("It is off")
is_on = True
Lastly you do not actually have is_on = True
in the global namespace so it cannot be referenced where you have it.
Either add it to your class init as a class attribute or move it out of the class to the global namespace.
Personally I would go with the class attribute route to avoid using global. The below version uses a class attribute instead of global.
Here is a corrected version of your code.
import customtkinter
# Setting up theme
customtkinter.set_appearance_mode("Dark") # Modes: "System" (standard), "Dark", "Light"
customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue"
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
# configure window
self.is_on = True
self.title("Cool Blue")
self.geometry(f"{1200}x{560}")
# configure grid layout (4x4)
self.grid_columnconfigure(1, weight=1)
self.grid_columnconfigure((2, 3), weight=0)
self.grid_rowconfigure((0, 1, 2, 3, 4), weight=1)
self.bind("<KeyPress>", self.key_pressed)
self.bind("<KeyRelease>", self.key_released)
###################################################################
# create sidebar frame for controls
###################################################################
self.sidebar_frame = customtkinter.CTkFrame(self, width=100)
self.sidebar_frame.grid(row=0, column=0, rowspan=1, padx=(5, 5), pady=(10, 10), sticky="nsew")
self.sidebar_frame.grid_rowconfigure(4, weight=1)
# Setting up grid label
self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="Motion",
font=customtkinter.CTkFont(size=15, weight="bold"))
self.logo_label.grid(row=0, column=1, padx=20, pady=(10, 10))
# Setting up W - Forward button
self.button_up = customtkinter.CTkButton(self.sidebar_frame, text="W", height=10, width=10)
self.button_up.grid(row=1, column=1, padx=20, pady=10, ipadx=10, ipady=10)
self.button_up.bind('<ButtonPress-1>', lambda x: self.motion_event_start(x, 'W'))
self.button_up.bind('<ButtonRelease-1>', lambda x: self.motion_event_stop(x, 'W'))
# Setting up S - Backwards buttons
self.button_down = customtkinter.CTkButton(self.sidebar_frame, text="S", height=10, width=10)
self.button_down.grid(row=3, column=1, padx=20, pady=10, ipadx=10, ipady=10)
self.button_down.bind('<ButtonPress-1>', lambda x: self.motion_event_start(x, 'S'))
self.button_down.bind('<ButtonRelease-1>', lambda x: self.motion_event_stop(x, 'S'))
# Setting up A - Left button
self.button_left = customtkinter.CTkButton(self.sidebar_frame, text="A", height=10, width=10)
self.button_left.grid(row=2, column=0, padx=10, pady=10, ipadx=10, ipady=10)
self.button_left.bind('<ButtonPress-1>', lambda x: self.motion_event_start(x, 'A'))
self.button_left.bind('<ButtonRelease-1>', lambda x: self.motion_event_stop(x, 'A'))
# Setting up D - Right button
self.button_right = customtkinter.CTkButton(self.sidebar_frame, text="D", height=10, width=10)
self.button_right.grid(row=2, column=2, padx=10, pady=10, ipadx=10, ipady=10)
self.button_right.bind('<ButtonPress-1>', lambda x: self.motion_event_start(x, 'D'))
self.button_right.bind('<ButtonRelease-1>', lambda x: self.motion_event_stop(x, 'D'))
###################################################################
# Create Sidebar for arm control
###################################################################
self.arm_control = customtkinter.CTkFrame(self)
self.arm_control.grid(row=1, column=0, rowspan=1, padx=(5, 5), pady=(10, 10), sticky="nsew")
self.arm_control.grid_rowconfigure(2, weight=1)
# Setting up grid label
self.arm_label = customtkinter.CTkLabel(self.arm_control, text="Arm",
font=customtkinter.CTkFont(size=15, weight="bold"))
self.arm_label.grid(row=0, column=0, padx=20, pady=(10, 10))
self.grip_label = customtkinter.CTkLabel(self.arm_control, text="Grip",
font=customtkinter.CTkFont(size=15, weight="bold"))
self.grip_label.grid(row=0, column=1, padx=20, pady=(10, 10))
# Arm Up
self.button_arm_up = customtkinter.CTkButton(self.arm_control, text=" Up ", height=10, width=10)
self.button_arm_up.grid(row=1, column=0, padx=10, pady=10, ipadx=30, ipady=10)
# Arm Down
self.button_arm_down = customtkinter.CTkButton(self.arm_control, text=" Down", height=10, width=10)
self.button_arm_down.grid(row=2, column=0, padx=10, pady=10, ipadx=30, ipady=10)
self.button_grip_open = customtkinter.CTkButton(self.arm_control, text="Open", height=10, width=10)
self.button_grip_open.grid(row=1, column=1, padx=10, pady=10, ipadx=30, ipady=10, sticky="w")
self.button_grip_close = customtkinter.CTkButton(self.arm_control, text="Close", height=10, width=10)
self.button_grip_close.grid(row=2, column=1, padx=10, pady=10, ipadx=30, ipady=10, sticky="w")
###################################################################
# Create Sidebar for grip
###################################################################
self.lights_control = customtkinter.CTkFrame(self)
self.lights_control.grid(row=3, column=0, rowspan=1, padx=(5, 5), pady=(10, 10), sticky="nsew")
self.lights_control.grid_rowconfigure(1, weight=1)
# LED Lights
self.led_switch = customtkinter.CTkSwitch(master=self.lights_control, text="LED",
command= self.led_switch)
self.led_switch.grid(row=0, column=1, pady=10, padx=20, sticky="n")
# Regular Lights
self.regular_ligths_switch = customtkinter.CTkSwitch(master=self.lights_control, text="Lights",
command=lambda: print("switch 1 toggle"))
self.regular_ligths_switch.grid(row=1, column=1, pady=10, padx=20)
# Camera
self.led_switch = customtkinter.CTkSwitch(master=self.lights_control, text="Camera",
command=lambda: print("switch 1 toggle"))
self.led_switch.grid(row=2, column=1, pady=10, padx=20, )
# create Video Canvas
self.picam = customtkinter.CTkCanvas(self, width=800, background="gray")
self.picam.grid(row=0, column=1, rowspan=4, padx=(5, 5), pady=(20, 20), sticky="nsew")
self.picam.grid_rowconfigure(4, weight=1)
self.picam_label = customtkinter.CTkLabel(master=self.picam, text="Live Stream",
font=customtkinter.CTkFont(size=20, weight="bold"))
self.picam_label.grid(row=0, column=2, columnspan=1, padx=10, pady=10, sticky="")
# create radiobutton frame
self.temperature = customtkinter.CTkFrame(self)
self.temperature.grid(row=0, column=3, rowspan=1, padx=(5, 5), pady=(10, 10), sticky="n")
self.temperature.grid_rowconfigure(2, weight=1)
self.label_temperature = customtkinter.CTkLabel(master=self.temperature, text="Temperature")
self.label_temperature.grid(row=0, column=2, columnspan=1, padx=10, pady=10, sticky="")
# create checkbox and switch frame
self.pressure = customtkinter.CTkFrame(self)
self.pressure.grid(row=1, column=3, rowspan=1, padx=(5, 5), pady=(10, 10), sticky="n")
self.pressure.grid_rowconfigure(1, weight=1)
self.label_pressure = customtkinter.CTkLabel(master=self.pressure, text="Pressure")
self.label_pressure.grid(row=0, column=2, columnspan=1, padx=10, pady=10, sticky="")
# create checkbox and switch frame
self.humidity = customtkinter.CTkFrame(self)
self.humidity.grid(row=3, column=3, rowspan=1, padx=(5, 5), pady=(10, 10), sticky="")
self.humidity.grid_rowconfigure(1, weight=1)
self.label_humidity = customtkinter.CTkLabel(master=self.humidity, text="Humidity")
self.label_humidity.grid(row=0, column=2, columnspan=1, padx=10, pady=10, sticky="")
def key_pressed(self, event):
if event.char in 'wads':
self.motion_event_start(event, event.char.upper())
def key_released(self, event):
if event.char in 'wads':
self.motion_event_stop(event, event.char.upper())
def motion_event_start(self, event, button):
# if button == "W":
# kit1.motor1.throttle = 1
# kit2.motor1.throttle = 1
# elif button == "S":
# kit1.motor1.throttle = -1
# kit2.motor1.throttle = -1
print(f"{button} Pressed")
def motion_event_stop(self, event, button):
print(f"{button} Released")
# kit1.motor1.throttle = 0
# kit2.motor1.throttle = 0
# Switch
def led_switch(self, event=None):
if self.is_on:
print("It is on")
self.is_on = False
else:
print("It is off")
self.is_on = True
if __name__ == "__main__":
app = App()
app.mainloop()
From my testing this fixes your issue: