how can i change the state of a button made with TTK in Python after i clicked it ? I want to disable the button START after i press it once and re-enable it after pressing STOP. I want this because my code creates a new duplicated thread everytime i press Start … so… i want to disable it… I used TTK instead of TK cause i saw it looks better but i cant seem to figure out how to use a global variable that just flips the state of that START button after i press it …
Example :
frm2=ttk.Button(frm, text="Start", command=start_button).grid(column=0, row=3)
This is my entire script so you can run it yourself and see what i mean …
from tkinter import * from tkinter import ttk import pyautogui import keyboard import time import threading gvar = False def imagedetect(): while gvar: if pyautogui.locateOnScreen('image.png', confidence = 0.9) != None: print("I can see it") time.sleep(1) else: print("I am unable to see it") time.sleep(1) #root.after(1000,imagedetect) def start_button(): global gvar gvar = True th_runner = threading.Thread(target=imagedetect, daemon=True) th_runner.start() def on_start(): global gvar gvar = True def on_stop(): global gvar gvar = False def help(): filewin = Toplevel(root, padx=50,pady=50) information = Label(filewin, text="App made by ..... you can close the app after starting it by pressing the key Q") information.pack() root = Tk() root.title("Rename me later") menubar = Menu(root) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label="Help", command=help) filemenu.add_separator() menubar.add_cascade(label="Info", menu=filemenu) frm = ttk.Frame(root, padding=30) frm.pack() ttk.Label(frm, text="App made by uknown").grid(column=1, row=0) frm2=ttk.Label(frm, text="").grid(column=0, row=1) frm2=ttk.Label(frm, text="").grid(column=1, row=1) frm2=ttk.Label(frm, text="").grid(column=2, row=1) frm2=ttk.Label(frm, text="").grid(column=0, row=2) frm2=ttk.Label(frm, text="").grid(column=1, row=2) frm2=ttk.Label(frm, text="").grid(column=2, row=2) frm2=ttk.Button(frm, text="Start", command=start_button).grid(column=0, row=3) frm2=ttk.Button(frm, text="Stop", command=on_stop).grid(column=1, row=3) frm2=ttk.Button(frm, text="Quit", command=root.destroy).grid(column=2, row=3) #root.destroy root.config(menu=menubar) #imagedetect() root.mainloop()
Advertisement
Answer
Why did you use the same variable for multiple widgets? It doesn’t work like that because a variable can only contain one value. If you want to change the button state later then you have to have separate variable names. Also you first have to create a button and then grid it. Not doing them in one line because you see grid returns none so that means you actually stored none in the variable instead of the widget class.
To change the state of button you do this btn.config(state=DISABLED OR NORMAL)
This should work:
from tkinter import * from tkinter import ttk import pyautogui import keyboard import time import threading gvar = False def imagedetect(): while gvar: if pyautogui.locateOnScreen('image.png', confidence = 0.9) != None: print("I can see it") time.sleep(1) else: print("I am unable to see it") time.sleep(1) #root.after(1000,imagedetect) def start_button(): global gvar, btn btn.config(state=DISABLED) gvar = True th_runner = threading.Thread(target=imagedetect, daemon=True) th_runner.start() def on_start(): global gvar gvar = True def on_stop(): global gvar btn.config(state=NORMAL) gvar = False def help(): filewin = Toplevel(root, padx=50,pady=50) information = Label(filewin, text="App made by ..... you can close the app after starting it by pressing the key Q") information.pack() root = Tk() root.title("Rename me later") menubar = Menu(root) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label="Help", command=help) filemenu.add_separator() menubar.add_cascade(label="Info", menu=filemenu) frm = ttk.Frame(root, padding=30) frm.pack() ttk.Label(frm, text="App made by uknown").grid(column=1, row=0) # You may need to change the names of these variables frm2=ttk.Label(frm, text="").grid(column=0, row=1) frm2=ttk.Label(frm, text="").grid(column=1, row=1) frm2=ttk.Label(frm, text="").grid(column=2, row=1) frm2=ttk.Label(frm, text="").grid(column=0, row=2) frm2=ttk.Label(frm, text="").grid(column=1, row=2) frm2=ttk.Label(frm, text="").grid(column=2, row=2) btn=ttk.Button(frm, text="Start", command=start_button) # Button is a class not a nonetype btn.grid(column=0, row=3) frm2=ttk.Button(frm, text="Stop", command=on_stop).grid(column=1, row=3) # This below is what 'frm2' will be equal to at the end so other widgets are lost so if need to use them later then you have to have seperate variables frm2=ttk.Button(frm, text="Quit", command=root.destroy).grid(column=2, row=3) #root.destroy root.config(menu=menubar) #imagedetect() root.mainloop()