Home > OS >  Python tkinter dynamic checkbutton method
Python tkinter dynamic checkbutton method

Time:02-06

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()

CodePudding user response:

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().

CodePudding user response:

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()
  • Related