Question

I'm having trouble with using the Entry box widget in tkinter. I want to have a new window to open when the user selects Edit -> Backbone... . In this window there will be a number of Entry widgets (just one coded for below for simplicity) that show default Strings stored in various instances the class Elements. The user should be able to edit this string and save it by clicking OK and returning it to its default value by clicking default. The entry box should always show the current value of the variable each time the backbone editor is reopened (If the whole program is restarted it does not need to remember the user input).

Upon opening the 'Backbone Editor' window the Entry box should show the string text variable but I can't make it appear.

from tkinter import *
from tkinter import ttk

class View(ttk.Frame):
    """Main GUI class"""

    def __init__(self, master = None):

        self.WIDTH = 450
        self.HEIGHT = 500

        self.lib = MolecularLibrary()

        # Set up the main window
        ttk.Frame.__init__(self, master, borderwidth=5, width=self.WIDTH, height=self.WIDTH)
        self.master.resizable(FALSE, FALSE)
        self.grid(column=0, row=0, sticky=(N, S, E, W))
        self.columnconfigure(0, weight=1)

        self.create_menus()

    def create_menus(self):
        """Produces the menu layout for the main window"""

        self.master.option_add('*tearOff', FALSE)

        self.menubar = Menu(self.master)
        self.master['menu'] = self.menubar

        # Menu Variables
        menu_edit = Menu(self.menubar)

        # Add the menus to the menubar and assign their variables
        self.menubar.add_cascade(menu=menu_edit, label = "Edit")

        ### Edit ###
        menu_edit.add_command(label="Backbone...", command=lambda : self.edit_backbone())


    def edit_backbone(self):
        """Shows a window where the backbone constituents can be edited"""
        backbone_window = Toplevel(borderwidth = 5)
        backbone_window.title("Backbone Editor")
        backbone_window.resizable(FALSE, FALSE)

        print("sugar value", self.lib.sugar_var)

        # LABELS FOR BACKBONE #
        # Phosphate annotations and input
        sugar_label = ttk.Label(backbone_window, text = "Sugar")

        #inputs
        sugar = ttk.Entry(backbone_window, textvariable = self.lib.sugar_var, justify = 'center', width=10)

        ### Buttons ###
        default = ttk.Button(backbone_window, text = "Defaults", command=lambda : defaults())
        okay = ttk.Button(backbone_window, text = "Okay", command=lambda : okay())
        cancel = ttk.Button(backbone_window, text = "Cancel", command=lambda : backbone_window.destroy())

        #content.grid(column=0, row=0)
        sugar_label.grid(column=2, row=1)
        sugar.grid(column=1, row=2, columnspan=3)

        default.grid(column=0, row=12, columnspan=3, pady=2)
        okay.grid(column=6, row=12, columnspan=3, pady=2)
        cancel.grid(column=9, row=12, columnspan=4, pady=2)

        backbone_window.focus()

        def defaults():
            """Reset the backbone and bases to their defaults."""

            self.lib.set_molecules()


        def okay():
            """Set the backbone and base variables to the user set values."""

            self.lib.sugar_var.new_formula(sugar.get())

            backbone_window.destroy()


class MolecularLibrary:
    """
    """

    def __init__(self, atom_file = r'C:\MyPyProgs\OSeq\resources\ATOMS.txt',
                 precision = 4):

        self.molecules = {}
        self.atom_file = atom_file
#         self.molecule_file = molecule_file

        # Variables
        self.set_molecules()


    def set_molecules(self):
        """
        Set all of the molecules for the backbone and bases to their default values and forumlae.
        """
                ### Sugar ###
        self.sugar_var = Element('C5H8O3', 'A')


    def add_molecule(self, molecule):
        """(MolecularLibrary, list) -> None
           Returns a dictionary of the molecule name as an Element
           {molecule[0]: Element}
        """
        print(molecule)
        tmp = self.get_mass(molecule[1])
        return {molecule[0]: Element(molecule[1], molecule[0], tmp[0], tmp[0])}

class Element:
    """
    Creates an element with the following construct:
    [symbol, name, monoisotopic, average]
    """

    def __init__(self, symbol, name):

        self.symbol = symbol
        self.name = name

    def __str__(self):

        return str([self.symbol, self.name])

    def get_name(self):
        """Returns the name of the Element"""

        return self.name

    def get_symbol(self):
        """Returns the symbol of the Element"""

        return self.symbol

    def new_formula(self, new_formula):
        """replace the formula with new_formaula and recalculate the 
           average and monoisotopic masses."""

        self.symbol = new_formula


if __name__ == "__main__":
    root = Tk()
    root.title("Sequencer")
    view = View(root)
    root.mainloop()

The code above is a heavily stripped version of my program but has the same basic architecture. I'm afraid there is still quite a lot of code, I would normally try strip it down more, but I'm not sure if the issue I'm having is from the architecture or not.

Was it helpful?

Solution

In order to use the textvariable attribute, you must give it an instance of a tkinter variable: StringVar, IntVar, BooleanVar, or DoubleVar

A good starting point to learn more about these variables is here: http://effbot.org/tkinterbook/variable.htm

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top