Chris
Chris

Reputation: 1027

Python tkinter dynamic checkbutton method

I have a settings page with lots of checkbuttons on it so I am trying to reduce the code but I am struggling when it comes to getting the checkbutton value to work so far I have:-

def _create_checkbox(self, label, index, state=0):
    x = label.replace(" ", "-").lower()
    self.settings_list[x] = state

    ttk.Label(self.settings_frame, text=label).grid(
        row=index, column=0)
    ttk.Checkbutton(
        self.settings_frame, variable=self.settings_list[x]
    ).grid(row=index, column=1)

the idea was to put the checkbutton names in a dict and then update the dict with the value but it is not working as planned, with my code all checkbutton values update as if they were one.

example list:

self.settings_list = {"force-gamemode": "0", "allow-cheats": "1"}

Edit to show minimal working example, I did originally try to use variables (IntVar) but it failed (I cant remember why) but that's why I then switched to a dict:-

import tkinter as tk
from tkinter import ttk


class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("tkinter dynamic checkbox example")
        self.geometry("700x450")

        self.settings_list = {"force-gamemode": "0", "allow-cheats": "1"}

        self.settings_frame = tk.Frame(self)
        self.settings_frame.grid(row=0, column=0)

        # create settings content
        self._create_checkbox("Force Gamemode", 0, 0)
        tk.Label(
            self.settings_frame, text="Label to show content between checkboxes"
        ).grid(row=1, column=0)
        self._create_checkbox("Allow Cheats", 2, 0)

        tk.Button(
            self.settings_frame,
            text="Create Properties File",
            command=self._create_properties,
        ).grid(row=3, column=0, sticky="ew")

    def _create_checkbox(self, label, index, state=0):
        x = label.replace(" ", "-").lower()

        self.settings_list[x] = state
        ttk.Label(self.settings_frame, text=label).grid(
            row=index, column=0, padx=5, pady=5, sticky="w"
        )
        ttk.Checkbutton(self.settings_frame, variable=self.settings_list[x]).grid(
            row=index, column=1, padx=5, pady=5, sticky="w"
        )

    def _create_properties(self):
        print(self.settings_list["force-gamemode"])
        print(self.settings_list["allow-cheats"])


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

Upvotes: 0

Views: 299

Answers (2)

kimhyunju
kimhyunju

Reputation: 344

In addition to acw1668's answer, to check the value

    def _create_properties(self):
        print(self.settings_list["force-gamemode"].get())
        print(self.settings_list["allow-cheats"].get())

so your code is ...

import tkinter as tk
from tkinter import ttk


class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("tkinter dynamic checkbox example")
        self.geometry("700x450")
        self.settings_list = {"force-gamemode": "0", "allow-cheats": "0"}
        self.settings_frame = tk.Frame(self)
        self.settings_frame.grid(row=0, column=0)

        # create settings content
        self._create_checkbox("Force Gamemode", 0, 0)
        tk.Label(self.settings_frame, text="Label to show content between checkboxes"
                 ).grid(row=1, column=0)
        self._create_checkbox("Allow Cheats", 2, 0)
        tk.Button(self.settings_frame, text="Create Properties File",
                  command=self._create_properties
                  ).grid(row=3, column=0, sticky="ew")

    def _create_checkbox(self, label, index, state=0):
        x = label.replace(" ", "-").lower()
        self.settings_list[x] = tk.IntVar(value=state)
        ttk.Label(self.settings_frame, text=label
                  ).grid(row=index, column=0, padx=5, pady=5, sticky="w")
        ttk.Checkbutton(self.settings_frame, variable=self.settings_list[x]
                        ).grid(row=index, column=1, padx=5, pady=5, sticky="w")

    def _create_properties(self):
        print(self.settings_list["force-gamemode"].get())
        print(self.settings_list["allow-cheats"].get())

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

Upvotes: 2

acw1668
acw1668

Reputation: 46669

Since you passed an integer 0 as the textvariable option of those Checkbutton widgets, an implicit IntVar will be created with name "0" for them. Therefore they will be changed together because they share same tkinter variable.

You need to change

self.settings_list[x] = state

to

self.settings_list[x] = tk.IntVar(value=state)

inside _create_checkbox().

Upvotes: 1

Related Questions