Search code examples
pythonclasstkinterinitself

mutliple entry widgets and one button widget in tkinter


I am trying to make two entry boxes and an 'OK' button that processes both entries: I don't understand the init() function or the reason 'self' has to be include in doing this. I want to access the entries outside this class and mainloop. The entries should be string type.

from tkinter import *
root = Tk()
root.geometry("550x145+500+300")

class myDose:
    def __init__(self):

        l1 = Label(text="Enter the prescription dose to three (3) decimal places [cGy]").pack()
        e1 = Entry(root)
        e1.pack()

        l2 = Label(text="Save new excel file as...").pack()
        e2 = Entry(root)
        e2.pack()

        l3 = Label(text="click 'OK', and then close window.").pack()

        b = Button(root, text="OK", command=submit)
        b.pack()

    def submit(self):
        print(e1.get())
        print(e2.get())

D = myDose()
root.mainloop()

#I want to access the entries, e1 and e2, outside the mainloop
print(D.e1)
print(D.e2)

Solution

  • The problem is that mainloop doesn't exit until the root window is destroyed. Once the root window is destroyed you can no longer access the widgets inside the root window. You can, however, access non-widget attributes of the object.

    If that is what you want -- to destroy the window and have access to the values in the widget -- you need to save the values before destroying the window.

    For example, in your submit you could save the values like this:

    def submit(self):
        self.data = {"e1": self.e1.get(), "e2": self.e2.get()}
    

    Once the window is destroyed, you still have a reference to the application object, so you can still access the non-widget attributes of the class:

    ...
    D = myDose(root)
    root.mainloop()
    
    print D.data["e1"]
    print D.data["e2"]
    

    Based on comments to the original question, you mention that later in your code you'll need to use askopenfilename. if that is the case, you should reconsider the need to run code after mainloop. Tkinter is designed to have a root window created exactly once, and for the program to exit immediately after mainloop exits.

    You can write programs however you want, but I think your code will be easier to maintain and modify over the long run if you stick to normal design patterns. Move your "real" code into a method of the app class and that will eliminate all of the problems associated with widgets being destroyed.