Search code examples
pythontkinterlabeltkinter-entry

Tkinter, Python: How do I save text entered in the Entry widget? How do I move a label?


I am a newbie at programming and my program is not stellar but hopefully it's ok because I have only been using it for a couple days now.

I am having trouble in my class "Recipie". In this class I am having trouble saving the text in my Entry widget. I know to use the .get() option but when I try to print it, it doesn't (whether it is within that defined method or not). So that is my main concern. I want it to save the text entered as a string when I press the button: b.

My other minor question is, how can I move the label. When I have tried I have used the height and width options, but that just expands the label. I want to move the text to create a title above my Entry boxes. Is label the right widget to use or would it be easier to use a message box widget? So it would look like, for example (but like 8 pixels down and 20 to the right):

ingredients
textbox
button labeled as: add an ingredient

And I am not sure the option .pack(side="...") or .place(anchor="...") are the right options to use for my buttons or entry boxes or labels.

And if you could add comments to your code explaining what you did, that would be so helpful.

import Tkinter
class Cookbook(Tkinter.Tk):
    def __init__(self):
        Tkinter.Tk.__init__(self)
        self.title("Cookbook")
        self.geometry("500x500+0+0")

        self.button = []
        for r in range(1):
            for c in range(1):
                b = Button(self).grid(row=r,column=c)
                self.button.append(b)

class Button(Tkinter.Button):
    def __init__(self,parent):
            b = Tkinter.Button.__init__(self, parent, text="Add A New Recipie", height=8, width=15, command=self.make_window)

    def make_window(self):
        popwindow = Recipie()
        popwindow.name()
        popwindow.ingredients()
        popwindow.addingredient()
        popwindow.savebutton()
        popwindow.save()

class Recipie(Tkinter.Tk):
    def __init__(self):
        Tkinter.Tk.__init__(self)
        self.title("New Recipie")
        self.geometry("500x500")

    def name(self):
        name = Tkinter.Label(self, text="Title:")
        name.pack() #used to be name.place(anchor="nw")

        self.insert_name = Tkinter.Entry(self) #edited with the answer below, used to be insert_name = Tkinter.Entry(self)
        self.insert_name.pack() #edited with the answer from below, used to be insert_name.pack()
        self.insert_name.focus_set() #edited with the answer from below, used to be insert_name.focus_set()

    def ingredients(self):
        self.e = Tkinter.Entry(self) #edited with the answer from below, used to be e.get()
        self.e.pack() #edited with the answer from below, used to be e.pack()
        self.e.focus_set() #edited with the answer from below, used to be e.focus_set()

    def addingredient(self):
        but = Tkinter.Button(self, text="Add Ingredients", width=15, command=self.ingredients)
        but.pack(side="bottom")

    def procedure(self):
        txt = Tkinter.Label(self, text="List the Steps:")
        txt.place(anchor="n")

        self.p = Tkinter.Entry(self) #edited with the answer from below, used to be p = Tkinter.Entry(self)
        self.p.place(anchor="nw") #edited with the answer from below, used to be p.place(anchor="nw")
        self.p.focus_set() #edited with the answer from below, used to be p.focus_set

    def savebutton(self):
        print self.insert_name.get() #edited with the answer from below
        print self.e.get() #edited with the answer from below
        print self.p.get() #edited with the answer from below

   def save(self):
         b = Tkinter.Button(self, text="Save Recipie", width=15,command=self.savebutton)
         b.pack()

top = Cookbook()
top.mainloop()

Solution

  • Part 1...

    You are currently defining your entry widget as a local variable inside the ingredients method (i.e. these are variables that only exist inside the method). To maintain a reference to the entry widget you are creating, you can assign it as an instance attribute to your Recipie object.

    i.e.

    e = Tkinter.Entry(self)
    e.pack()
    e.focus_set()
    

    becomes

    self.e = Tkinter.Entry(self)
    self.e.pack()
    self.e.focus_set()
    

    and

    print e.get()
    

    becomes

    print self.e.get()
    

    Some required reading before you continue with Python:

    Python classes

    Explaining 'self' in Python

    Part 2...

    So in answer to the second part of the question on how to position your labels. It just looks like you need to alter the way in which you are packing widgets. An example of how to pack entry widgets is a clean way (emulating the functionality of your example) would be:

    import Tkinter as tk
    
    class IngredientAdder(tk.Tk):
        def __init__(self):
            tk.Tk.__init__(self)
            self.geometry("500x500+0+0")
            self.init_gui()
    
        # function to add new ingredients
        def add_ingredient_entry(self):
            entry = tk.Entry(self)
            entry.pack(side=tk.TOP)
            self.ingredient_entries.append(entry)
    
        # get contents of all entry boxes
        def save_recipe(self):
            for ingredient in self.ingredient_entries:
                print ingredient.get()
            print "[Recipe saved]"
    
        # build initial widgets 
        def init_gui(self):
    
            # this is a list of ingredients entry boxes
            self.ingredient_entries = []
    
            # put a label at the top of the window and anchor it there
            tk.Label(self,text="Ingredients").pack(anchor=tk.N,side=tk.TOP)
    
            # Put these two buttons at the bottom of the window and anchor them there
            tk.Button(self,text="Save recipe",command=self.save_recipe).pack(anchor=tk.S,side=tk.BOTTOM)
            tk.Button(self,text="Add ingredient",command=self.add_ingredient_entry).pack(anchor=tk.S,side=tk.BOTTOM)
    
            # new ingredients will be added between the label and the buttons 
            self.add_ingredient_entry()
    
    cookbook = IngredientAdder()
    cookbook.mainloop()