Python Forum

Full Version: Inserting Numerical Value to the Element in Optionlist and Printing it into Entry
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello. I'm just learning Python. I have confronted a problem in my study.

I have an optionlist for building types (Residential, Museum, Hospital, Hotel etc.) but I need to convert these building types into numbers (fire load 'MJ/kg').

In other words, I want each building type to have its own "Numerical data of fire load".

For example, I would like "Museum" to appear in the option list, but when I select the museum, "100" should be written in the relevant entry.

How can it be done? Thank you in advance. Smile


options_list = {"Museum": 100,
"School": 200,
"Library": 300,
"House": 400,
"Bath": 500}

value_inside = tkinter.StringVar(Variable)
value_inside.set("Pick a Building Type")

question_menu = tkinter.OptionMenu(window, value_inside, *options_list)
question_menu.place(x=395, y=253)

building_types = tkinter.Entry(window, textvariable=value_inside, state=NORMAL, bd=5, fg='black',
font=("Helvetica", 12, BOLD))
building_types.place(x=292, y=255, width=100, height=30)
This code creates a dictionary capable menu option class.
import tkinter as tk

class MyOptionMenu(tk.OptionMenu):
    """An option menu that takes a dictionary instead of a list.
    I display the dictionary keys, but I return the dictionary values.
    """
    def __init__(self, parent, options, width=None, command=None):
        self.values = options
        self.keys = {value: key for key, value in options.items()}
        self.var = tk.StringVar(parent, list(options.keys())[0])
        self.var.trace('w', self._value_changed)
        super().__init__(parent, self.var, *options.keys())
        self.command = command
        if width is not None:
            self['width'] = width

    def _value_changed(self, *_):
        """Called when self.var is written.  Call callback function."""
        if self.command:
            self.command(self.value)

    @property
    def value(self):
        """Return the value of the selected option"""
        return self.values[self.var.get()]

    @value.setter
    def value(self, new_value):
        """Set the selected option by value"""
        self.var.set(self.keys[new_value])

    @property
    def key(self):
        """Return the selected option"""
        return self.var.get()

    @key.setter
    def key(self, new_key):
        """Set the selected option"""
        self.var.set(new_key)


class Window(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        frame = tk.Frame(self)
        label = tk.Label(frame, text="Pick a Building Type")
        self.option_menu = MyOptionMenu(
            frame,
            {"Museum": 100, "School": 200, "Library": 300, "House": 400, "Bath": 500},
            width=20,
            command=self.select_option)
        self.display = tk.Label(self, width=20)
        frame.pack(padx=20, pady=20)
        label.pack(side=tk.LEFT)
        self.option_menu.pack(side=tk.LEFT, padx=(5, 0))
        self.display.pack(side=tk.TOP, padx=20, pady=(0, 20))
        self.option_menu.value = 100

    def select_option(self, value):
        self.display['text'] = f'{self.option_menu.key} = {value}'


Window().mainloop()
You could write a class like this that makes OptionMenu work the way you like, or your can have the option menu call a function in your program that converts the selection to the matching value. The important part is tying a function to the user making a selection. In the example above this is done by adding a trace to the option menu variable. Another way to do this is specify a "command" callback when creating the option menu.