0

I'm new to tkinter, and what I'm trying to do is the following:

  • Open a file dialog window to select a text file. (Done)
  • Process the information of the file. (Done)
  • Show in a tkinter window some of the information of the file. (Done)
  • User selects some checkboxes from the previous tkinter window, the window then is closed, and the information from checkboxes is used later in the code. (Not working)

This is the code I have, probably not the best way to manage tkinter stuff.

# Import tkinter for file/directory dialogs.
from tkinter import *

# Definition of the structure of file's regions
# Just want to keep titles and subtitles in this part.
class SectionHeaders:
    def __init__(self, title, subtitles = []):
        self.title = title
        self.subtitles = subtitles

class CheckboxesMap():
    # fileSections is a list of SectionHeaders objects.
    def __init__(self, parent=None, fileSections=[]):
        # List of variables for each checkbox.
        self.vars = []
        # Helper variable
        r = 0
        for fileSection in fileSections:
            # Variable and checkbox for the title.
            var = IntVar()
            chk = Checkbutton(parent, text=fileSection.title, variable=var)
            chk.grid(row = r, column = 0, sticky = W)
            self.vars.append(var)
            r+=1
            for subtitle in fileSection.subtitles:
                var = IntVar()
                chk = Checkbutton(parent, text=subtitle, variable=var)
                chk.grid(row = r, column = 1, sticky = W)
                self.vars.append(var)
                r+=1

    def get_states(self):
        return map((lambda var: var.get()), self.vars)

# Function to run at the second tkinter window closing.
def closing_action(something, tkinstance=None):
    if tkinstance != None:
        tkinstance.destroy()
    if isinstance(something, CheckboxesMap):
        print(list(something.get_states()))

def main():
    # Creating instance of Tk, initializing tcl/tk interpreter.
    # We need to create this Tk instance and withdraw it in order to
    # initialize the interpreter.
    root = Tk()
    # Avoiding to keep the Tk window open, withdraw hides it.
    root.withdraw()

    ##### Some processing of the file content #####
    ## titles variable referenced below is a list
    ## of SectionHeaders objects.
    ## Added as part of EDIT 1.
    titles = []
    titles.append(SectionHeaders('Title 1', []))
    titles.append(SectionHeaders('Title 2', ['Subtitle 2.1', 'Subtitle 2.2']))
    titles.append(SectionHeaders('Title 3', ['Subtitle 3.1']))

    # Creating a selection tool with the titles listed.
    title_window = Tk()
    tk_titles = CheckboxesMap(title_window, titles)

    # The following three commands are needed so the window pops
    # up on top on Windows...
    title_window.iconify()
    title_window.update()
    title_window.deiconify()

    title_window.protocol("WM_DELETE_WINDOW", closing_action(tk_titles, root))
    title_window.mainloop()

    # Obtaining variable states
    print(list(tk_titles.get_states()))

Second Tkinter window

Even with the selections as per the image, I'm getting the following in the console: [0, 0, 0, 0, 0, 0, 0]

Any ideas on how to keep these values even after the tkinter window is closed? What could be improved from what I have for tkinter stuff handling?

EDIT 1: Added titles list that can be used for the example. EDIT 2: Leaving minimal code example.

Helbirah
  • 61
  • 9
  • in the loop where you also create intvars: `var = IntVar()` each iteration this gets overwritten so basically all the widgets that had this as a `textvariable` will now point to the last one and if it is 0, then well all will be 0 and vice versa, also you should provide a [mre] – Matiiss Jul 22 '21 at 18:58
  • It would be easier to help if you provide a [mre]. – Henry Jul 22 '21 at 19:29
  • Does this answer your question? [How to save a data after closing a window?](https://stackoverflow.com/questions/55363748/how-to-save-a-data-after-closing-a-window) – K450 Jul 22 '21 at 19:38
  • 1
    I see that you're creating multiple instances of `Tk()`. Vars (among various other Tkinter objects) are tied to a specific instance, and simply will not work with widgets contained in a different instance - but there's generally no error if you violate this requirement, it just doesn't work. The easiest solution is to have only one `Tk()`, and use `Toplevel()` instead to create additional windows. – jasonharper Jul 22 '21 at 19:39
  • 1
    @K450, in the link you provided they are using the first instance of Tk, and I declared more than one because I need the interpreter prior to call filedialog, but not sure if I can "hide", modify and "redraw" the same instance to be used later in the code. – Helbirah Jul 22 '21 at 19:46

1 Answers1

0

I found the solution to the problem here. It is because you don't specify the parent for the IntVar.
Just change

var = IntVar()

to

var = IntVar(parent)

One other issue I noticed (I assume this isn't intentional) is that the function that is called when the window is closed is called immediately when the program is run. To fix this change the title_window.protocol line to

title_window.protocol("WM_DELETE_WINDOW", lambda: closing_action(tk_titles, root))

to prevent this.

Henry
  • 3,472
  • 2
  • 12
  • 36