1

I'm sure it is a simple mistake and I've localized it to a specific spot in the code:

class NewProduct(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)                

        tLabel = ttk.Label(self, text="Title: ", font=NORM_FONT).grid(row=0, padx=5, pady=5)
        qLabel = ttk.Label(self, text="Quantity: ", font=NORM_FONT).grid(row=1, padx=5, pady=5)
        pLabel = ttk.Label(self, text="Price: $", font=NORM_FONT).grid(row=2, padx=5, pady=5)
        te = ttk.Entry(self).grid(row=0, column=1, padx=5, pady=5) # Add validation in the future
        qe = ttk.Entry(self).grid(row=1, column=1, padx=5, pady=5)
        pe = ttk.Entry(self).grid(row=2, column=1, padx=5, pady=5)

        saveButton = ttk.Button(self, text="Save", command=lambda: self.save(self.te.get(), self.qe.get(), self.pe.get()))
        #WHY IS THIS WRONG!!!!!???!?!?!?!?!?
        saveButton.grid(row=4, padx=5)
        cancelButton = ttk.Button(self, text="Cancel", command=lambda: popupmsg("Not functioning yet."))
        cancelButton.grid(row=4, column=1, padx=5)

    def save(self, title, quantity, price):
        conn = sqlite3.connect("ComicEnv.db")
        c = conn.cursor()
        c.execute("INSERT INTO cdata(unix, datestamp, title, quantity, price) VALUES (?,?,?,?,?)",
                  (time.time(), date, title, quantity, price))
        conn.commit()
        conn.close()

I've tried a few different things including: saveButton = ttk.Button(self, text="Save", command=lambda: self.save(te.get(), qe.get(), pe.get()))

I'm trying to get the user input from the entry widget and store it in a sqlite3 database.

This is the Traceback:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python34\lib\tkinter\__init__.py", line 1533, in __call__
    return self.func(*args)
  File "C:\Users\aedwards\Desktop\deleteme.py", line 106, in <lambda>
    saveButton = ttk.Button(self, text="Save", command=lambda: self.save(self.te.get(), self.qe.get(), self.pe.get()))
AttributeError: 'NewProduct' object has no attribute 'te'

Any help you guys could give me would be greatly appreciated. Any more information, please just let me know.

Thanks in advance!

Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52
Silight
  • 37
  • 7
  • 1
    1. When assigning attributes of a class, do `self.te = whatever`, not `te = whatever`. 2. Don't assign and pack on the same line. See http://stackoverflow.com/questions/1101750/python-tkinter-attributeerror-nonetype-object-has-no-attribute-get – Kevin Apr 01 '15 at 16:02
  • Could it be that simple? I'll try it now. – Silight Apr 01 '15 at 16:11
  • That did it. Thanks SO much. I didn't even to think to look at the grid part. All that research and it was because I asked the wrong questions. Thanks again! – Silight Apr 01 '15 at 16:21

1 Answers1

6

The error is telling you the problem: The NewProduct object has no attribute named te. You have created a local variable named te, but for it to be an attribute you must create self.te.

Also, you must call grid in a separate statement from where you create the widget, because grid(...) returns None, so te or self.te will also be none. This not only solves that problem, but makes your code easier to understand, because you can put all of your calls to grid in the same block of code so you don't have your layout scattered all over the place.

For example:

def __init__(...):
    ...
    self.te = ttk.Entry(...)
    self.qe = ttk.Entry(...)
    self.pe = ttk.Entry(...)
    ...
    self.te = grid(...)
    self.qe = grid(...)
    self.pe = grid(...)

FWIW, I recommend not using lambda here. Create a proper function for your button to call. It's much easier to write and debug than a complicated lambda. There's rarely a need to use lambda in tkinter.

For example:

def __init__(...):
    ...
    saveButton = ttk.Button(..., command=self.on_save)
    ...

def on_save(self):
    title=self.te.get()
    quantity = self.qe.get()
    price = self.pe.get()
    self.save(title, quantity, price):
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • That does simplify the code a bit. I will change that. Thanks a lot. – Silight Apr 01 '15 at 16:50
  • The `def on_save ...` statement must be executed before the `ttk.Button` call. This is not an issue if `def` is a method within a class and the call part of a set-up gui method of the same class. – Terry Jan Reedy Apr 01 '15 at 17:14