Search code examples
python-3.xtkinter

TKinter: Populate a combobox based on content generated within a function


The code below (simplified) has a Button that when pressed will generate a list. I would like to populate the Combobox with this output.

This is not happening. I tried 4 attempts (remarked in code) but I either get an error or nothing happens.

PS: .grid is not working as expected. The button is on top of the Entry rather than next to it. I still need to figure that part out.

import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from tkinter.filedialog import askopenfilename
import os.path
import tempfile


class UIScreen(ttk.Frame):

    def __init__(self, master):
        super().__init__(master, padding=15)
        self.filename = ttk.StringVar()
        self.racivalues = []
        self.pack(fill=BOTH, expand=YES)
        self.create_widget_elements()

    def create_widget_elements(self):
        style = ttk.Style()
        file_entry = ttk.Entry(self, textvariable=self.filename, state=READONLY)
        file_entry.grid(row=0, column=0, columnspan=3, padx=20, pady=20, sticky="we")

        browse_btn = ttk.Button(self, text="Browse", command=self.open_file)
        browse_btn.grid(row=0, column=1, padx=20, pady=20, sticky="e")
        
        raci_label = ttk.Label(self, text="RACI Styles")
        raci_label.grid(row=1, column=0, padx=20, pady=20, sticky="w")

        raci_combo = ttk.Combobox(self, values=self.racivalues)
        raci_combo.grid(row=1, column=1, columnspan=3, padx=20, pady=20, sticky="e")

    def open_file(self):
        # function populates this var
        xml_styles = ["A", "B", "C", "D"]



         
        # populate the raci_combo
        # self.master.raci_combo['values'] = xml_styles  # AttributeError: '_tkinter.tkapp' object has no attribute 'raci_combo'
        # self.master.racivalues = xml_styles  # did not work

        # self.raci_combo['values'] = xml_styles  # AttributeError: 'UIScreen' object has no attribute 'raci_combo'
        self.racivalues = xml_styles   # did not work




        # populate the text box
        self.filename.set("Done")


if __name__ == '__main__':

    app = ttk.Window("combo", "sandstone", size=(800,400), resizable=(True, True))
    UIScreen(app)
    app.mainloop()

The code sample above is fully functional and demonstrates the problem.

I expect the Combobox raci_combo to contain within it "A", "B", "C". D" list.


Solution

  • You should define raci_combo as an instance variable and then access it from any part of your code.

    Here's the corrected code:

    import ttkbootstrap as ttk
    from ttkbootstrap.constants import *
    from tkinter.filedialog import askopenfilename
    import os.path
    import tempfile
    
    class UIScreen(ttk.Frame):
        def __init__(self, master):
            super().__init__(master, padding=15)
            self.filename = ttk.StringVar()
            self.racivalues = []
            self.pack(fill=BOTH, expand=YES)
            self.create_widget_elements()
    
        def create_widget_elements(self):
            style = ttk.Style()
            file_entry = ttk.Entry(self, textvariable=self.filename, state=READONLY)
            file_entry.grid(row=0, column=0, columnspan=3, padx=20, pady=20, sticky="we")
    
            browse_btn = ttk.Button(self, text="Browse", command=self.open_file)
            browse_btn.grid(row=0, column=1, padx=20, pady=20, sticky="e")
            
            raci_label = ttk.Label(self, text="RACI Styles")
            raci_label.grid(row=1, column=0, padx=20, pady=20, sticky="w")
    
            self.raci_combo = ttk.Combobox(self, values=self.racivalues)
            self.raci_combo.grid(row=1, column=1, columnspan=3, padx=20, pady=20, sticky="e")
    
        def open_file(self):
            xml_styles = ["A", "B", "C", "D"]
    
            self.raci_combo['values'] = xml_styles
            self.racivalues = xml_styles
    
            self.filename.set("Done")