How do I change a Checkbuttons state in TTK?

Question:

I’m creating a list of Checkbuttons which highlight when selected, when another Checkbutton is selected I want to deselect the other buttons,

I have two buttons in my code when my button ‘create booking’ is toggled on or off it calls clear_previous_selection. Here I try and change the state of my other button ‘viewFilmListing’ to be un-highlighted although no matter what I set the state to it doesn’t seem to want to unselect.

Here are some of my combinations and outputs:
Film listing selected without create booking ever being selected (Terminal)
Film listing selected without create booking ever being selected (GUI)

Create booking selected then Film listing selected after (Terminal)
Create booking selected then Film listing selected after (GUI)

Film listing toggled on then off then Create booking selected (Terminal)
Film listing toggled on then off then Create booking selected (GUI)

My code:

import tkinter as tk
from tkinter import ttk
import sv_ttk

class App(tk.Tk):

    def __init__(self):
        super().__init__()
        sv_ttk.use_dark_theme()

        self.geometry('1200x800')
        self.title("Menu")
        self.resizable(0,0)

        self.columnconfigure(0, weight=2)
        self.columnconfigure(1, weight=0)

        rowCount = 0

        self.createBooking = ttk.Checkbutton(self, text="View film listing", style="Toggle.TButton",command=lambda : self.button_selection(0))
        self.createBooking.grid(column=0, row=rowCount, sticky=tk.W, padx=5, pady=5)
        rowCount+=1
        self.viewFilmListing = ttk.Checkbutton(self, text="Create booking", style="Toggle.TButton",command=lambda : self.button_selection(1))
        self.viewFilmListing.grid(column=0, row=rowCount, sticky=tk.W, padx=5, pady=5)
        

    def clear_previous_selection(self):
        print("We are clearing selections")
        print(self.viewFilmListing.state())
        self.viewFilmListing.configure(state='alternate')
        self.viewFilmListing.update_idletasks()

        
    def button_selection(self, option):
        if(option == 0): 
            print(0)       
            self.clear_previous_selection()
            #Call view film listing
            return
        elif(option == 1):
            print(1)
            #Call create booking
            return
        else:
            return

        
if __name__ =="__main__":
    app=App()
    app.mainloop()

I tried setting the state to ‘disabled’, this greys the button out and I can’t de-disable it.

I’ve tried a few combinations of changing the state (‘False’, 0, ”, ‘alternate’, ‘normal’), hopefully my question is clear. None of the combinations stated above worked.

Asked By: OttoLuck

||

Answers:

import tkinter as tk
from tkinter import ttk
import sv_ttk


class App(tk.Tk):

    def __init__(
            self
            ):
        super().__init__()
        sv_ttk.use_dark_theme()

        self.geometry('1200x800')
        self.title("Menu")
        self.resizable(False, False)

        self.columnconfigure(0, weight=2)
        self.columnconfigure(1, weight=0)
        self.createBookingVar = tk.BooleanVar()
        self.viewFilmListingVar = tk.BooleanVar()
        self.variables = [self.createBookingVar, self.viewFilmListingVar]
        rowCount = 0

        self.createBooking = ttk.Checkbutton(
            self,
            text="View film listing",
            style="Toggle.TButton",
            variable=self.createBookingVar,
            onvalue=True,
            offvalue=False,
            command=lambda: self.handle_button_click(self.createBookingVar)
            )
        self.createBooking.grid(column=0, row=rowCount, sticky=tk.W, padx=5, pady=5)
        rowCount += 1
        self.viewFilmListing = ttk.Checkbutton(
            self,
            text="Create booking",
            style="Toggle.TButton",
            variable=self.viewFilmListingVar,
            onvalue=True,
            offvalue=False,
            command=lambda: self.handle_button_click(self.viewFilmListingVar)
            )
        self.viewFilmListing.grid(column=0, row=rowCount, sticky=tk.W, padx=5, pady=5)

    def handle_button_click(self, variable: tk.BooleanVar):
        for var in self.variables:
            if var != variable:
                var.set(False)


if __name__ == "__main__":
    app = App()
    app.mainloop()

The solution is to use Tk variables. You could mask this handle_button_click function into some other as you please, but this should cover your use-case.

Answered By: KazzyJr

To change the state of the Checkbutton you can use :

.state(['!selected']) # clear the checkbox


import tkinter as tk
from tkinter import ttk
import sv_ttk

class App(tk.Tk):

    def __init__(self):
        super().__init__()
        sv_ttk.use_dark_theme()

        self.geometry('1200x600')
        self.title("Menu")
        self.resizable(0,0)

        self.columnconfigure(0, weight=2)
        self.columnconfigure(1, weight=0)

        rowCount = 0

        self.createBooking = ttk.Checkbutton(self, text="View film listing", style="Toggle.TButton",command=lambda : self.button_selection(0))
        self.createBooking.grid(column=0, row=rowCount, sticky=tk.W, padx=5, pady=5)
        rowCount+=1
        self.viewFilmListing = ttk.Checkbutton(self, text="Create booking", style="Toggle.TButton",command=lambda : self.button_selection(1))
        self.viewFilmListing.grid(column=0, row=rowCount, sticky=tk.W, padx=5, pady=5)
        

    def clear_previous_selection(self):
        #print("We are clearing selections")
        self.viewFilmListing.state(['!selected'])
        
        #print(self.viewFilmListing.state())
        #self.viewFilmListing.configure(state='alternate')
        #self.viewFilmListing.update_idletasks()

        
    def button_selection(self, option):
        if(option == 0): 
            print(0)       
            self.clear_previous_selection()
            #Call view film listing
            return
        elif(option == 1):
            print(1)
            self.createBooking.state(['!selected'])
            #Call create booking
            return
        else:
            return

        
if __name__ =="__main__":
    app=App()
    app.mainloop()
Answered By: AziMez
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.