"Disabled" Buttons Still Clickable. - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: "Disabled" Buttons Still Clickable. (/thread-41749.html) |
"Disabled" Buttons Still Clickable. - Nd4SpdSe - Mar-12-2024 Hello. I've never been good a programming, and I know I'm trying to run before learning to walk, but it's kind of how I work by learning when I have a need to learn something, it's because I have a goal in mind. I've been up and down this issue for months and totally stuck at this one. It's likely simple fix for those that are experienced, but I just can't find a solution that I can make work, or even understand. Heck, my buddy did much of the code as mine was much worse. Functional, but not efficient, but at least I could understand mine cause I'm not good with loops and variables, despite that pretty much being the basics of programming... I'm working on making some accessory controls for my truck. Part of it is controls for the winch and I want to implement a few safety systems in software. I did the in-out safety interlock done, but the next one is a two-setup system so I need to activate the "Winch Controls" before the "Feed In" and "Feed Out" options are available. This is to avoid accidental activation. While it does look like it works, the buttons can be activated despite being disabled, then it's free-for-all that seems to even bypass the IN/OUT safety interlock. I've seen the clickable-yet-disabled buttons being is a known issue,. but I just don't understand how to fix it. If someone could give me a hand I would be greatly appreciated. Even more of a help would be if you could do the code in a manner that's more simplistic for me to understand as opposed to being the more efficient way. It would really help me learn. # ************************************************************************** # # **** **** # # ******************** Crappy code by Michel Fortin *********************** # # **** # # ********************* Better code by Fred Poirier *********************** # # **** # # ************************************************************************** # # **** **** # # ********** Based from code by www.TheEngineeringProjects.com ************* # # **** **** # # **************** How to Create a GUI in Raspberry Pi 3 ******************* # # **** **** # # ************************************************************************** # # Importing Libraries import RPi.GPIO as GPIO import time from tkinter import * import tkinter.font import tkinter as tk # Raspberry Pi 4 Pin Settings #Création de la liste des sorties SWITCH = [0 for i in range(14)] Button_Press = [0 for i in range(14)] Button_N = [0 for i in range(14)] TextSW = [0 for i in range(14)] Output_State = [0 for i in range(14)] SBC = [0] WinchStat = [0] for i in range(14): SWITCH[i] = (i) GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) # We are accessing GPIOs according to their physical location GPIO.setup(SWITCH[i], GPIO.OUT) # We have set our LED pin mode to output GPIO.output(SWITCH[i], GPIO.LOW) # When it will start then LED will be OFF # GUI basic settings Gui = Tk() Gui.title("---") Gui.config(background= "#818589") Gui.minsize(800,600) Font1 = tkinter.font.Font(family = 'Helvetica', size = 18, weight = 'bold') # GUI Controls def SW_ON(Param1, Param2, Param3, Param4, Param5, Param6): if (Output_State[Param1] == 0): GPIO.output(SWITCH[Param1], GPIO.HIGH) #Switch ON Button_Press[Param1]["fg"] = "GREEN" TextSW[Param1] = Label(Gui,text=' ON ', font = Font1, bg = Param2, fg='BLACK', padx = 0) TextSW[Param1].grid(row=Param3,column=Param4) Output_State[Param1] = 1 if (Param6 == 1) : Button_Press[Param1+1]["state"] = "normal" TextSW[7] = Label(Gui,text=SBC[0], font = Font1, bg = 'Orange', fg='BLACK', padx = 20) TextSW[7].grid(row=4,column=2) if (Param6 == 3) : Button_Press[Param1+1]["state"] = "normal" Button_Press[Param1+2]["state"] = "normal" else : GPIO.output(SWITCH[Param1], GPIO.LOW) #Switch OFF Button_Press[Param1]["fg"] = "BLACK" TextSW[Param1] = Label(Gui,text='_____', font = Font1, bg='#818589', fg='#818589', padx = 1) TextSW[Param1].grid(row=Param3,column=Param4) Output_State[Param1] = 0 if (Param6 == 1): Button_Press[Param1+1]["state"] = "disabled" TextSW[7] = Label(Gui,text='_____', font = Font1, bg='#818589', fg='#818589', padx = 1) TextSW[7].grid(row=4,column=2) if (Param6 == 2): Button_Press[Param1+1]["state"] = "disabled" TextSW[3] = Label(Gui,text='_____', font = Font1, bg='#818589', fg='#818589', padx = 1) TextSW[3].grid(row=2,column=2) if (Param6 == 3) : Button_Press[Param1+1]["state"] = "disabled" Button_Press[Param1+2]["state"] = "disabled" # Cycling Mode Count for Front Spot Light Modes def SWITCH3() : GPIO.output(SWITCH[3], GPIO.HIGH) SBC[0] += 1 if (SBC[0] == 7) : SBC[0] = 1 TextSW[3] = Label(Gui,text=SBC[0], font = Font1, bg = 'Orange', fg='BLACK', padx = 20) TextSW[3].grid(row=2,column=2) # Cycling Mode Count for Rear Signal Bar Modes def SWITCH7() : GPIO.output(SWITCH[7], GPIO.HIGH) SBC[0] += 1 if (SBC[0] == 9) : SBC[0] = 1 TextSW[7] = Label(Gui,text=SBC[0], font = Font1, bg = 'Orange', fg='BLACK', padx = 20) TextSW[7].grid(row=4,column=2) #Conditions to momentary press winch buttons, plus opposing button interlock def button12_pressed(): Button_Press[13]["state"] = "disabled" GPIO.output(SWITCH[12], GPIO.HIGH) print('Winch IN') def button12_released(): Button_Press[13]["state"] = "normal" Button_Press[12]["state"] = "normal" GPIO.output(SWITCH[12], GPIO.LOW) print('Winch OFF (IN)') def button13_pressed(): Button_Press[12]["state"] = "disabled" GPIO.output(SWITCH[13], GPIO.HIGH) print('Winch OUT') def button13_released(): Button_Press[12]["state"] = "normal" Button_Press[13]["state"] = "normal" GPIO.output(SWITCH[13], GPIO.LOW) print('Winch OFF (Out)') # Function for Buttons started here #Switch 1 - Foward Roof Mounted Light Bar Controls Button_Press[1] = Button(Gui, text='Front Light Bar', font = Font1, command=lambda a=1, b='Yellow', c=2, d=0, e='Front Light Bar', f=0: SW_ON(a, b, c, d, e, f), bg='bisque2', height = 1, width = 16) Button_Press[1].grid(row=1,column=0) #Switch 2 - Brush Buard Spot Lights - Main Power Button_Press[2] = Button(Gui, text='Front Spot Lights', font = Font1, command=lambda a=2, b='Orange', c=2, d=1, e='Front Spot Lights', f=2: SW_ON(a, b, c, d, e, f), bg='bisque2', height = 1, width = 16) Button_Press[2].grid(row=1,column=1) #Switch 3 - Brush Buard Spot Lights - Mode Type Selection Button_Press[3] = Button(Gui, text='Front Spot Mode', font = Font1, command = SWITCH3, fg='Green', bg='bisque2', height = 1, width = 16, state = 'disabled') Button_Press[3].grid(row=1,column=2) #Column Spacer Text0 = Label(Gui,text='', font = Font1, bg='#818589', fg='green', padx = 0) Text0.grid(row=2,column=0) #Switch 5 - Rear LED Light Bar Button_Press[5] = Button(Gui, text='Rear Light Bar', font = Font1, command=lambda a=5, b='Yellow', c=4, d=0, e='Rear Light Bar', f=0: SW_ON(a, b, c, d, e, f), bg='bisque2', height = 1, width = 16) Button_Press[5].grid(row=3,column=0) #Switch 6 - Rear Facing Signal Bar - Main Power Button_Press[6] = Button(Gui, text='Rear Signal Bar', font = Font1, command=lambda a=6, b='Orange', c=4, d=1, e='Rear Signal Bar', f=1: SW_ON(a, b, c, d, e, f), bg='bisque2', height = 1, width = 16) Button_Press[6].grid(row=3,column=1) #Switch 7 - Rear Facing Signal Bar - Mode Type Selection Button_Press[7] = Button(Gui, text='Signal Bar Mode', font = Font1, command = SWITCH7, fg='Green', bg='bisque2', height = 1, width = 16, state = 'disabled') Button_Press[7].grid(row=3,column=2) #Column Spacer Text0 = Label(Gui,text='', font = Font1, bg='#818589', fg='green', padx = 0) Text0.grid(row=4,column=0) #Switch 8 - Activation Front TRE Electric Differential Locker - M205 @ 3.36 Button_Press[8] = Button(Gui, text='Front Diff Lock', font = Font1, command=lambda a=8, b='#899499', c=6, d=0, e='Front Diff Lock', f=0: SW_ON(a, b, c, d, e, f), bg='bisque2', height = 1, width = 16) Button_Press[8].grid(row=5,column=0) #Switch 9 - Activation Rear TRE Electric Differential Locker - R230 @ 3.36 Button_Press[9] = Button(Gui, text='Rear Diff Lock', font = Font1, command=lambda a=9, b='#899499', c=6, d=1, e='Rear Diff Lock', f=0: SW_ON(a, b, c, d, e, f), bg='bisque2', height = 1, width = 16) Button_Press[9].grid(row=5,column=1) #Switch 10 - Remote Power Signal for Xantrex 2000W A/C Pure Sine Wave Inverter under the passenger seat Button_Press[10] = Button(Gui, text='A/C Inverter', font = Font1, command=lambda a=10, b='#899499', c=6, d=2, e='A/C Inverter', f=0: SW_ON(a, b, c, d, e, f), bg='bisque2', height = 1, width = 16) Button_Press[10].grid(row=5,column=2) #Column Spacer Text0 = Label(Gui,text='', font = Font1, bg='#818589', fg='green', padx = 0) Text0.grid(row=6,column=0) #Switch 11 - Main Power for In-Cab Winch Controls Button_Press[11] = Button(Gui, text='Winch Controls', font = Font1, command=lambda a=11, b='Red', c=8, d=0, e='Winch Controls', f=3: SW_ON(a, b, c, d, e, f), bg='bisque2', height = 1, width = 16) Button_Press[11].grid(row=7,column=0) #Switch 12 - Winch Signal - Feed Line In Button_Press[12] = Button(Gui, text='Winch Feed IN', font = Font1, command = GPIO.output(SWITCH[12], GPIO.HIGH), bg='bisque2', height = 1, width = 16, state = "disabled") Button_Press[12].grid(row=7,column=1) Button_Press[12].bind("<ButtonPress>", lambda event : button12_pressed()) Button_Press[12].bind("<ButtonRelease>", lambda event : button12_released()) #Switch 13 - Winch Signal - Feed Line Out Button_Press[13] = Button(Gui, text='Winch Feed OUT', font = Font1, command = GPIO.output(SWITCH[13], GPIO.HIGH), bg='bisque2', height = 1, width = 16, state = "disabled") Button_Press[13].grid(row=7,column=2) Button_Press[13].bind("<ButtonPress>", lambda event : button13_pressed()) Button_Press[13].bind("<ButtonRelease>", lambda event : button13_released()) Text0 = Label(Gui,text='', font = Font1, bg='#818589', fg='green', padx = 0) Text0.grid(row=8,column=0) Text3 = Label(Gui,text='-----', font = Font1, bg = '#000000', fg='#FFFFFF', padx = 10, pady = 10) Text3.grid(row=9,columnspan=4) Gui.mainloop() RE: "Disabled" Buttons Still Clickable. - menator01 - Mar-12-2024 I don't know if this is what you're after but, a quick example of using radiobuttons to disable buttons. import tkinter as tk root = tk.Tk() root.geometry('800x400+350+350') # Set the default value to off for correct radiobutton selected to be on state = tk.StringVar(value='off') # Function for changing button state def changestate(change): if change == 'on': button1['state'] = 'disabled' button2['state'] = 'disabled' else: button1['state'] = 'normal' button2['state'] = 'normal' # Container for radiobuttons top = tk.LabelFrame(root, text='Safety Toggle') top.pack(side='top', padx=5, pady=5, fill='x') # Radiobuttons to toggle button state. Set values to have a default setting on = tk.Radiobutton(top, text='ON', variable=state, value='off') on['command'] = lambda: changestate('on') on.pack(side='left', padx=5, pady=5) off = tk.Radiobutton(top, text='OFF', variable=state, value='on') off['command'] = lambda: changestate('off') off.pack(side='left', padx=5, pady=5) # Container for buttons buttons = tk.LabelFrame(root, text='Buttons') buttons.pack(side='top', padx=5, pady=5, fill='x') # Create buttons with default state of disabled button1 = tk.Button(buttons, text='Button 1', state='disabled') button1.pack(side='left', padx=5, pady=5) button2 = tk.Button(buttons, text='Button 2', state='disabled') button2.pack(side='left', padx=5, pady=5) root.mainloop() RE: "Disabled" Buttons Still Clickable. - deanhystad - Mar-13-2024 The "<ButtonPresss>" event is a mouse button press, not the button widget press. You can see this if you run the code below. Clicking on a label generates a <ButtonPress> event. import tkinter as tk class Window(tk.Tk): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) button = tk.Button(self, text="Push me", state=tk.DISABLED, command=lambda: print("Clicked")) button.pack(padx=50, pady=50) button.bind("<ButtonPress>", lambda event: print("Pressed")) label = tk.Label(self, text="Me too!") label.pack(padx=50, pady=50) label.bind("<ButtonPress>", lambda event: print("Label Pressed")) Window().mainloop()What you want is not a normal button behavior, so you'll have to write it yourself. The code below implements a button that calls a command when pressed and when released. The button cannot be pressed when disabled. The code also shows how you can make a toggle button and a button for stepping through a series of switch values. import tkinter as tk FRONT_LIGHT_BAR = 1 FRONT_SPOT_LIGHTS = 2 FRONT_SPOT_MODE = 3 REAR_LED_BAR = 4 REAR_SIGNAL_BAR = 5 REAR_BAR_MODE = 6 WINCH_IN = 7 WINCH_OUT = 8 class OnOffButton(tk.Button): """A button that sends a message when pressed and released.""" def __init__(self, *args, command=None, **kwargs): super().__init__(*args, **kwargs) self.command = command self.bg = self["bg"] self.bind("<ButtonPress>", lambda x: self._button_event(True)) self.bind("<ButtonRelease>", lambda x: self._button_event(False)) def _button_event(self, value): """Called when mouse button pressed when hovering over self.""" if self["state"] != tk.DISABLED and self.command: self["bg"] = self["activebackground"] if value else self.bg self.command(value) class ToggleButton(tk.Button): """A button that toggles between on and off.""" def __init__(self, *args, command=None, **kwargs): super().__init__(*args, command=self._clicked, **kwargs) self.command = command self.bg = self["bg"] self._value = False def _clicked(self): """Called when button is clicked. Toggle value and call command.""" self.value = not self.value @property def value(self): """Get toggled state. True is if button is pressed, False if button is released.""" return self._value @value.setter def value(self, value): """Set toggled state.""" self._value = value self["bg"] = self["activebackground"] if value else self.bg self["relief"] = tk.SUNKEN if value else tk.RAISED if self.command: self.command(self.value) class SwitchButton(tk.Button): """A button for stepping through a series of values.""" def __init__(self, *args, text, values, command=None, **kwargs): super().__init__(*args, command=self._clicked, **kwargs) self.text = text self.command = command self.values = values self.value = values[0] def _clicked(self): """Called when button is clicked. Toggle on and call command.""" self._index = (self._index + 1) % len(self.values) self.value = self.values[self._index] @property def value(self): """Get selected value.""" return self.values[self._index] @value.setter def value(self, value): """Set selected value.""" self._index = self.values.index(value) self["text"] = f"{self.text}: {self.value}" if self.command: self.command(self.value) class Window(tk.Tk): """Make a window with some buttons for demonstration purposes.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.front_light_bar = ToggleButton( self, text='Front Light Bar', activebackground="Yellow", command=lambda on: self._set_output(on, FRONT_LIGHT_BAR) ) self.front_light_bar.grid(row=0, column=0, sticky="news") self.front_spot_lights = ToggleButton( self, text='Front Spot Lights', activebackground="Orange", command=lambda on: self._set_output(on, FRONT_SPOT_LIGHTS) ) self.front_spot_lights.grid(row=0, column=1, sticky="news") self.front_spot_mode = SwitchButton( self, text='Front Spot Mode', bg="lightblue", values=list(range(1, 8)), command=lambda value: self._set_switch(value, FRONT_SPOT_MODE) ) self.front_spot_mode.grid(row=0, column=2, sticky="news") self.rear_led_bar = ToggleButton( self, text='Rear LED Bar', activebackground="Yellow", command=lambda on: self._set_output(on, FRONT_LIGHT_BAR) ) self.rear_led_bar.grid(row=1, column=0, sticky="news") self.rear_signal_bar = ToggleButton( self, text='Rear Signal Bar', activebackground="Orange", command=lambda on: self._set_output(on, REAR_SIGNAL_BAR) ) self.rear_signal_bar.grid(row=1, column=1, sticky="news") self.rear_bar_mode = SwitchButton( self, text='Rear Bar Mode', bg="lightblue", values=list(range(1, 10)), command=lambda value: self._set_switch(value, FRONT_SPOT_MODE) ) self.rear_bar_mode.grid(row=1, column=2, sticky="news") self.enable_winch = ToggleButton( self, text='Enable Winch', activebackground="yellow", command=self._enable_winch ) self.enable_winch.grid(row=2, column=0, sticky="news") self.winch_in = OnOffButton( self, text="Winch IN", state=tk.DISABLED, activebackground="red", command=lambda on: self._set_output(on, WINCH_IN)) self.winch_in.grid(row=2, column=1, sticky="news") self.winch_out = OnOffButton( self, text="Winch OUT", state=tk.DISABLED, activebackground="red", command=lambda on: self._set_output(on, WINCH_OUT)) self.winch_out.grid(row=2, column=2, sticky="news") def _set_output(self, on, pin): """Set a pin output.""" print(f"Setting pin {pin} to {on}") def _set_switch(self, value, switch): """Set a switch output.""" print(f"Setting switch {switch} to {value}") def _enable_winch(self, on): """Enable/disable the winch.""" state = tk.NORMAL if on else tk.DISABLED self.winch_in["state"] = state self.winch_out["state"] = state Window().mainloop() RE: "Disabled" Buttons Still Clickable. - laughorchestra - Mar-13-2024 # Importing Libraries import RPi.GPIO as GPIO from tkinter import * import tkinter.font # GPIO Setup GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) # Global Variables SWITCH = [i for i in range(14)] Button_Press = [0 for _ in range(14)] Output_State = [0 for _ in range(14)] SBC = [0] # GUI Initialization Gui = Tk() Gui.title("---") Gui.config(background="#818589") Gui.minsize(800, 600) Font1 = tkinter.font.Font(family='Helvetica', size=18, weight='bold') # Function to toggle switch state def toggle_switch(pin): Output_State[pin] = not Output_State[pin] GPIO.output(SWITCH[pin], GPIO.HIGH if Output_State[pin] else GPIO.LOW) # Function to handle button press def button_pressed(pin): Button_Press[pin]["state"] = "disabled" toggle_switch(pin) # Function to handle button release def button_released(pin): Button_Press[pin]["state"] = "normal" toggle_switch(pin) # GUI Controls for i in range(14): SWITCH[i] = i GPIO.setup(SWITCH[i], GPIO.OUT) GPIO.output(SWITCH[i], GPIO.LOW) Button_Press[i] = Button(Gui, text=f'Switch {i}', font=Font1, command=lambda pin=i: button_pressed(pin), bg='bisque2', height=1, width=16) Button_Press[i].grid(row=i, column=0) # Update the GUI Gui.mainloop()This code focuses on improving readability, organization, and functionality. Make sure to customize it according to your specific requirements and hardware setup. scratch geometry dash |