'str' object has no attribute 'get' in Tkinter callback - python

I'm trying to trace an OptionMenu widget's choice so that different choices run a different function. However, I keep running into the error below:
Exception in Tkinter callback
Traceback (most recent call last):
File "-", line 1705, in __call__
return self.func(*args)
File "-", line 149, in callback
self.bookingCanvas(optVar)
File "-", line 152, in bookingCanvas
perfDate = optVar.get()
AttributeError: 'str' object has no attribute 'get'
Here is the relevant code:
optVar = StringVar(self.root)
optVar.trace('r', callback=self.callback)
optVar.set("06/10/20") # default value
optMenu_Label = Label(self.root, text='Select a performance date:',bg='gray15', fg='yellow', relief=GROOVE)
optMenu_Label.pack(side=TOP, anchor=NW, padx=15, pady=15)
optMenu = OptionMenu(self.root, optVar, '04/10/20','5/10/20','6/10/20')
optMenu.pack(side=TOP,anchor=NW, padx=35, pady=3)
The callback of the .trace() above:
def callback(self, optVar, *args):
print("SOMETHING HAS CHANGED")
self.bookingCanvas(optVar)
The error area (I assume):
def bookingCanvas(self, optVar):
perfDate = optVar.get()
print("This is a Date >>>",perfDate)
print("did we get here?")

The callback from a trace is given the name of the variable, not a reference to the variable object. The name is a string, which is why you're getting the error AttributeError: 'str' object has no attribute 'get'.
With the name, you can use the common widget method getvar to get the value stored in the variable.
In your definition of callback you can get the value and pass it to your function like so: (assuming for this example that you have a global variable named 'root` which represents the root widget)
def callback(self, optVar_name, *args):
print("SOMETHING HAS CHANGED")
value = root.getvar(optVar_name)
self.bookingCanvas(value)
With that, you can remove the call to get in bookingCanvas:
def bookingCanvas(self, perfDate):
print("This is a Date >>>",perfDate)
print("did we get here?")

Related

What causes an exception in Tkinter callback? [duplicate]

This question already has an answer here:
TypeError: 'NoneType' object is not callable with tkinter
(1 answer)
Closed 1 year ago.
I'm trying to make a program that you can add infinite rooms to, so all of my code is built around using one variable to deduce which room is which. However when I run it, it gives me an error that doesn't directly reference any one line in my code, and since I'm a pretty new programmer, I don't know what it means. Also my code is pretty all over the place and incomplete. Thanks for any help!
The error
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\SCA0023\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
TypeError: 'NoneType' object is not callable
The Code
from tkinter import *
root = Tk()
class Room:
def __init__(self, items):
self.objects = []
self.objects.append(items)
def list(self):
print(self.objects)
def addkitchenmenu(r): #add a new option menu attributed to a new room
globals()[f'kitchenvar_{r}'] = StringVar(root)
globals()[f'kitchenvar_{r}'].set("Add an appliance")
globals()[f'kitchenvar_{r}'].trace('w', applianceadd(r))
kitchenitems = ['Kettle', 'Toaster']
globals()[f'appliancelist_{r}'] = OptionMenu(root, globals()[f'kitchenvar_{r}'], *kitchenitems).pack()
addkitchen(r)
def applianceadd(r): #add a new room
globals()[f'kobjects_{r}'] = []
globals()[f'kobjects_{r}'].append(globals()[f'kitchenvar_{r}'].get())
items = globals()[f'kobjects_{r}']
globals()[f'kroom_{r}'] = Room(items)
globals()[f'kroom_{r}'].list()
def addkitchen(r): #add an appliance
globals()[f'addappliace{r}'] = Button(root, text='add appliance', command=lambda: applianceadd(r))
def newkitchencheck(): #find the next name for a room that isn't taken
varnotfound = True
a = 0
while varnotfound:
if f'kroom{a}' in globals():
a += 1
else:
r = a
varnotfound = False
addkitchenmenu(r)
addroombutton = Button(root, text="add kitchen", command=newkitchencheck)
addroombutton.pack()
root.mainloop()
You are passing result of applianceadd(r) (which is None) to .trace(). Change to .trace("w", lambda *_: applianceaddr(r)).

Passing arguments down in Tkinter to a method

I'm struggling to get my method working correctly. I've thought about using a lambda function which I did for another problem and that worked, however here it does not seem to work. I'm trying to change the functions to methods and for some reason, my method is not working correctly since it has no reference to the tree. I've tried using a lambda function although that does not work.
My error:
NameError: name 'tree' is not defined
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.8/tkinter/__init__.py", line 1883, in __call__
return self.func(*args)
File "/home/bitvivaz/Documents/Software Development/Python/PasswordManager/mainFrame.py", line 54, in select
print([tree.item(x) for x in tree.selection()])
NameError: name 'tree' is not defined
Here is my code:
import tkinter as tk
import tkinter.ttk as ttk
from encryption import encrypted_password, decrypt_password
import backend as db
def get_credentials(tree):
'''Retrieves all credentials from the database and inserts it into the tree widget'''
for row in db.show_credentials():
tree.insert("", 'end', text=row['name'], values=(
row['username'], decrypt_password(row['password'])))
class MainframeApp:
def __init__(self, master=None):
# build ui
frame_main = ttk.Frame(master)
frame_main.config(height='600', width='600')
frame_main.grid()
# Creates tree widget
tree = ttk.Treeview(frame_main)
tree["columns"] = ("one", "two")
tree.column("#0")
tree.column("one")
tree.column("two")
tree.heading("#0", text="Website")
tree.heading("one", text="Username")
tree.heading("two", text="Password")
tree.grid(padx='5', pady='5', rowspan='20')
get_credentials(tree)
tree.bind("<<TreeviewSelect>>", self.select, "+")
button_add = ttk.Button(frame_main)
button_add.config(text='Add')
button_add.grid(column='1', padx='5', row='0')
button_delete = ttk.Button(frame_main)
button_delete.config(text='Delete')
button_delete.grid(column='1', padx='5', row='1')
button_logout = ttk.Button(frame_main)
button_logout.config(text='Logout')
button_logout.grid(column='1', padx='5', row='2')
# Main widget
self.mainwindow = frame_main
def select(self, e):
print([tree.item(x) for x in tree.selection()])
def run(self):
self.mainwindow.mainloop()
if __name__ == '__main__':
root = tk.Tk()
root.title("Password Manager")
app = MainframeApp(root)
app.run()
When you make use of a class structure, certain variables are available across methods (class or instance variables), others are not (local variables).
In your case, you need to define variables you need across methods as instance variables, that is, rather than:
tree = ttk.Treeview(frame_main)
You declare:
self.tree = ttk.Treeview(frame_main)
Then you can reference the variable across methods as self.tree.

get() from an Entry Box returns 'None' [duplicate]

This question already has answers here:
Tkinter: AttributeError: NoneType object has no attribute <attribute name>
(4 answers)
Closed 2 years ago.
recently I began to work with tkinter. I try to create a Grade manager and when I try to save the input from an Entry box, but every way I try, the result is an error or 'None'
def check_value(self,Input_Name):
Name = Input_Name.get()
print(Name)
def add_Student(self, window):
print("Yes")
Input_Name = tk.Entry(window, bg='blue').pack()
Button(window, text="Show", command=lambda: self.check_value(Input_Name)).pack()
For this piece of code the following error is :
Exception in Tkinter callback
Traceback (most recent call last): File "C:\Program
Files\WindowsApps\PythonSoftwareFoundation.Python.3.8_3.8.1520.0_x64__qbz5n2kfra8p0\lib\tkinter_init_.py",
line 1883, in call
return self.func(*args) File "C:/Users/User/PycharmProjects/pythonProject/main.py", line 28, in
Button(window, text="Show", command=lambda: self.check_value(window.Input_Name)).pack() File
"C:/Users/User/PycharmProjects/pythonProject/main.py", line 20, in
check_value
Name = Input_Name.get() AttributeError: 'NoneType' object has no attribute 'get'
You are trying to assign the Input_Name to the result that is returned by .pack() method of the widget, not to the widget itself. .pack() method returns nothing. Consequently, you are trying to .get() something from a Nonetype object instead of a tk.Entry.
You need to assign the tk.Entry to the Input_Name variable first, and then just call method pack on the variable. Here is an example of fixed code:
def check_value(self,Input_Name):
Name = Input_Name.get()
print(Name)
def add_Student(self, window):
print("Yes")
Input_Name = tk.Entry(window, bg='blue')
Input_Name.pack()
Button(window, text="Show", command=lambda: self.check_value(Input_Name)).pack()

AttributeError when using validatecommand on a Spinbox

I am doing a test writing a script that validate a spinbox to implement it on a larger system, but I am struggling with python because it is warning that there is no spinbox attribute on my Window class. Check my code:
from Tkinter import *
class Window:
def __init__(self, toplevel):
self.spinbox = Spinbox(toplevel, from_ = 0, to = 10,
validate = 'all', validatecommand = self.validate)
self.spinbox.pack()
def validate(self):
print self.spinbox.get()
root = Tk()
Window(root)
root.mainloop()
This is the error it is giving:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1486, in __call__
return self.func(*args)
File "D:\DOCS\FILIPE\PROGRAMMING\PYTHON\Tkinter sandbox\01 - spinbox validate.
py", line 13, in validate
print self.spinbox.get()
AttributeError: Window instance has no attribute 'spinbox'
Anyone could help me with this one?
If you add some print statements to your code:
class Window:
def __init__(self, toplevel):
print "A start", self, self.__dict__
self.spinbox = Spinbox(toplevel, from_ = 0, to = 10,
validate = 'all', validatecommand = self.validate)
self.spinbox.pack()
print "A end", self, self.__dict__
def validate(self):
print "B", self, self.__dict__
print self.spinbox.get()
#...
You get the output:
A start <__main__.Window instance at 0x7fe4f8deec20> {}
B <__main__.Window instance at 0x7fe4f8deec20> {}
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1532, in __call__
return self.func(*args)
File "t.py", line 14, in validate
print self.spinbox.get()
AttributeError: Window instance has no attribute 'spinbox'
A end <__main__.Window instance at 0x7fe4f8deec20> {'spinbox': <Tkinter.Spinbox instance at 0x7fe4f8e0da28>}
This means that the validate function is called inside the constructor to validate the initial value, and at that point self.spinbox has not yet been set. You will need to either check if you are still constructing or delay setting validatecommand like this:
self.spinbox = Spinbox(toplevel, from_ = 0, to = 10,
validate = 'all')
self.spinbox["validatecommand"] = self.validate
self.spinbox.pack()
I MANAGED TO SOLVE THE PROBLEM USING TEXTVARIABLES AND THE TRACE METHOD
#Validates
self.countstringvar = StringVar()
self.countstringvar.trace("w", lambda name, index, mode,
sv = self.countstringvar: self.noLettersValidate(sv, self.count))
self.starsstringvar = StringVar()
self.starsstringvar.trace("w", lambda name, index, mode,
sv = self.starsstringvar: self.noLettersValidate(sv, self.stars))
self.scorestringvar = StringVar()
self.scorestringvar.trace("w", lambda name, index, mode,
sv = self.scorestringvar: self.noLettersValidate(sv, self.score))
self.count['textvariable'] = self.countstringvar
self.stars['textvariable'] = self.starsstringvar
self.score['textvariable'] = self.scorestringvar
def removeLetters(self, s):
a = []
for i in s:
if i.isdigit():
a.append(i)
return ''.join(a)
def noLettersValidate(self, sv, w):
w.text(self.removeLetters(sv.get()))
Thanks for everyone contributions!

Problems with Tkinter Entry and .get()

I'm having problems with my Tkinter Entry widget.
I'm just testing things out and would like to have my callback print out whatever I typed out in Entry self.a. but I'm getting this error.
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in call
return self.func(*args) File "C:/Users/Andy/testimage.py", line 146, in get
print a.get(self) NameError: global name 'a' is not defined
I was wondering if someone can tell me what I'm doing wrong. I linked the callback function correctly because if I make it print "aasdfasd" instead, it will print that when I press the button.
def clicked_wbbalance(self):
self.top = Toplevel()
self.top.title("LASKJDF...")
Label(self.top, text="Enter low level").grid(row=0, column=0,padx=10)
Label(self.top, text="Enter high level").grid(row=1, column=0,padx=10)
Label(self.top, text="Values must be between 0 to 255").grid(row=3, column=0)
Button(self.top, text="Ok", command=self.get).grid(row=3, column = 1)
self.a =Entry(self.top).grid(row=0, column=1,padx=10)
self.b =Entry(self.top).grid(row=1, column=1,padx=10)
def get(self):
print self.a.get(self)
As RocketDonkey pointed out, your traceback does not match the code you posted.
Your code as written will generate a traceback like this:
AttributeError: 'NoneType' object has no attribute 'get'
The root problem is that grid returns None. That means that attributes a and b will be None because they are assigned the result of calls to grid. Fix that by puting object creation and widget placement on different lines:
self.a = Entry(self.top)
self.b = Entry(self.top)
self.a.grid(row=0, column=1,padx=10)
self.b.grid(row=1, column=1,padx=10)
You traceback says print a.get(self) NameError: global name 'a' is not defined, but the code you posted uses the syntax print self.a.get(self) (which would appear to be correct). Therefore if you check on line 146, you aren't prefacing a with self, meaning that instead of referencing the property a of the instance, you are trying to reference a on its own, which is not defined. Try adding self in front of a on line 146 and see if the problem continues.

Categories