Search code examples
pythonpython-3.xiniconfigparsertkinter.checkbutton

Passing a Boolean variable from configuration file to tkinter checkbox


I have a problem with the behavior of checkboxes when working with the configparser for Python. The checkbox should be either checked or unchecked depending on a Boolean variable stored in config.ini. But the checkbox is always unchecked, no matter how I define the entry in the configuration file.

Here is an example script

import tkinter as tk
import configparser

def load_config():
    config = configparser.ConfigParser()
    config.read('config.ini')
    return config

def config_window():
    configwin = tk.Toplevel(root)
    configwin.title("Config")

    config = load_config()

    number_var = tk.DoubleVar(value=config.getfloat('Settings', 'number'))
    status_var = tk.BooleanVar(value=config.getboolean('Settings', 'status'))

    label = tk.Label(configwin, textvariable=number_var)
    label.pack()
    checkbutton = tk.Checkbutton(configwin, text="Status", variable=status_var)
    checkbutton.pack()


root = tk.Tk()
root.title("Checkbox Test")

button = tk.Button(text="Open config", command=config_window)
button.pack()

root.mainloop()

And the corresponding config.ini:

[Settings]
number = 1.5
status = True

The result is not as expected

I added the number-label to check the basic program logic, which worked. Only the checkbox is not checked as expected. "status = True" and "status = False" both result in an unchecked checkbox. Lower case or "1" instead of "True" also do not lead to the desired result.


Solution

  • Your number_var and status_var are a local variables of config_window function, local variables will get garbage collected (un-referenced / deleted) when the function returns/ends, since the program thinks that only in the function will you need those variables, and you won't need it outside of it.

    Moving to global variable would solve your problem.

    Here's the edited code:

    import tkinter as tk
    import configparser
    
    root = tk.Tk()
    root.title("Checkbox Test")
    
    # global var and initialize the value as what ever you want to be default
    number_var = tk.DoubleVar(value=0)
    status_var = tk.BooleanVar(value=False)
    
    def load_config():
        config = configparser.ConfigParser()
        config.read('config.ini')
        return config
    
    def config_window():
        global number_var, status_var # grab them into your function
    
        configwin = tk.Toplevel(root)
        configwin.title("Config")
    
        config = load_config()
    
        # change the value to what you get from 'config.ini'
        number_var.set(config.getfloat('Settings', 'number'))
        status_var.set(config.getboolean('Settings', 'status'))
    
        label = tk.Label(configwin, textvariable=number_var)
        label.pack()
        checkbutton = tk.Checkbutton(configwin, text="Status", variable=status_var)
        checkbutton.pack()
    
    button = tk.Button(text="Open config", command=config_window)
    button.pack()
    
    root.mainloop()