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)).
Related
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()
Im having trouble calling an variable from a function within another function.
I have two functions:
def refineRate(event):
if refineRate(event) == int():
refine = int(refineRate(event))
return refine
else:
refine = float(refineRate(event))
return refine
and:
def veldCalc(event):
minValue = open("mineral_value.csv", "r")
veld = minValue.readlines()[0]
minValue.close()
veld = veld[0:3]
veld = int(veld)
veld = veld / 100 * refineRate(event)
refinedVeld = veld * int(veldCalc)
print (refinedVeld)
I also have two entry where the user of the calculator can enter some figures.
repro = Label(root, text="Reprocessing %")
repro_entry = Entry(root)
repro.grid(row=0, column=0)
repro_entry.grid(row=0, column=1)
veld = Label(root, text="Veldspar: ")
veld_entry = Entry(root)
veld.grid(row=1, column=0)
veld_entry.grid(row=1, column=1)
repro_entry.bind("<KeyPress>", refineRate)
veld_entry.bind("<KeyPress>", veldCalc)
What i need is for the user to input there refineRate and which should then get passed through the function and stored for later use. the when they enter the amount they have, the veldCalc function should then pull the users refine rate from the previous function and do the math but im getting the following errors
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Ganjena\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1699, in __call__
return self.func(*args)
File "C:/Users/Ganjena/Desktop/Course/Projects/helloworld/ORE FUNCTIONS/Ore Calculator.py", line 5, in refineRate
if refineRate(event) == int():
File "C:/Users/Ganjena/Desktop/Course/Projects/helloworld/ORE FUNCTIONS/Ore Calculator.py", line 5, in refineRate
if refineRate(event) == int():
File "C:/Users/Ganjena/Desktop/Course/Projects/helloworld/ORE FUNCTIONS/Ore Calculator.py", line 5, in refineRate
if refineRate(event) == int():
[Previous line repeated 990 more times]
RecursionError: maximum recursion depth exceede
any idea to why this isn't working? Thank you in advance.
You seem to have a misconception of how to get the user-input value inside a tk.Entry widget. The proper way is to use the .get() method on the widget.
Here is a minimal example to get you started:
# (Use Tkinter/tkinter depending on Python version)
import Tkinter as tk
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.repro = tk.Label(self, text="Reprocessing %")
self.repro_entry = tk.Entry(self)
self.repro.grid(row=0, column=0)
self.repro_entry.grid(row=0, column=1)
self.repro_entry.bind("<Return>", self.refineRate)
self.mainloop()
def refineRate(self, evt):
# Get the user input and print it in the terminal
userRepro = self.repro_entry.get()
print(userRepro)
# Launch the GUI
app = App()
Then, to check whether the user input is a float or an int, you can use the technique described in this link.
I'm trying to create an "Admin" section to a small program that executes some maths.
The admin button on the main TK window creates a top level window with an entry field that only turns on when the correct password is entered into a password field (or at least it will be when I figure out how to do this.)
The submit button is intended to update the global variable of a price that will then be remembered by the program from the entry field that would have the new price input by the user. The issue I'm having is how to make the global variable update and change and stay changed once this button is pressed.
This code is only designed to test the ability to do this but for the sake of context I will post it here anyways. Any help towards this goal would be fantastic.
The issue is that this code does not work, it wont allow me to alter the global variables, and produces the error the variable int has no attribute append?
Further - So append was the wrong move, fair enough, the problem i have is that global12mmprice = 200 is not updating the globalvariable and at other points in the program it is still referencing the original value. Is there a way to completely update the global variable so that the program will reflect the new value and the old one will no longer exist?
global12mmprice = 86.67
global15mmprice = 191.19
int12mmprice = int(global12mmprice)
int15mmprice = int(global15mmprice)
class mainwindow(tk.Frame):
def __init__(self, root):
tk.Frame.__init__(self, root)
b1 = tk.Button(self, text="Glass Table", command = self.glsqWindow)
b1.grid(column=1,row=2,pady=50,padx=10)
self.count = 0
b2 = tk.Button(self, text='Round Table', command = self.glrnWindow)
b2.grid(column=2,row=2,pady=50,padx=10)
self.count = 0
b3 = tk.Button(self, text='Console Table', command = self.glcnWindow)
b3.grid(column=3,row=2,pady=50,padx=10)
self.count = 0
b4 = tk.Button(self, text='Admin', command = self.admin)
b4.grid(column=4,row=2,pady=50,padx=10)
self.count = 0
def admin(self):
self.count += 1
window = tk.Toplevel(self)
window.geometry("600x350+300+300")
def submit():
int12mmprice.append(200)
b1 = tk.Button(window,text='Submit', command=submit)
b1.grid(column=3,row=2,pady=50,padx=10)
There is alot more code after this but this is the relevant part. Also any general advice you might have is of course welcome.
ANSWER:- Provided with alot of assistance from "fdhsdrg". This is the solution that i implemented to get the desired result for anyone who has this question in future.
As was explained to me i needed to create a file that the program could read and write to that would create the necessary information for the program to access and alter as and when needed.
import tkinter as tk
from tkinter import *
from tkinter import Tk, Frame, Menu
import tkinter.messagebox as box
import pickle, os
file=open('prices.dat','rb')
data=pickle.load(file)
file.close
global12mmprice = data[0]
global15mmprice = data[1]
class mainwindow(tk.Frame):
def __init__(self, root):
tk.Frame.__init__(self, root)
b1 = tk.Button(self, text="Glass Table", command = self.glsqWindow)
b1.grid(column=1,row=2,pady=50,padx=10)
self.count = 0
b2 = tk.Button(self, text='Round Table', command = self.glrnWindow)
b2.grid(column=2,row=2,pady=50,padx=10)
self.count = 0
b3 = tk.Button(self, text='Console Table', command = self.glcnWindow)
b3.grid(column=3,row=2,pady=50,padx=10)
self.count = 0
b4 = tk.Button(self, text='Admin', command = self.admin)
b4.grid(column=4,row=2,pady=50,padx=10)
self.count = 0
def admin(self):
self.count += 1
window = tk.Toplevel(self)
window.geometry("600x350+300+300")
def submit():
global data
data[0] = '86.67'
file=open('prices.dat','wb')
pickle.dump(data,file)
file.close
global root
box.showinfo('Administration','The program will now terminate and the prices will be updated.')
root.destroy()
b1 = tk.Button(window,text='Submit', command=submit)
b1.grid(column=3,row=2,pady=50,padx=10)
As you can see the data list in the .dat file gets updated, later i will replace this with a get.entry() field but for now this demonstrates the intended design. You might want to consider using resetboard instead of destroy if you want the program to automatically relaunch after closing.
Well, the error message you added pretty much explains everything.
int12mmprice is an Integer, which does not have the method append. Append is a method which can be used on objects of type List:
>>> a=9
>>> type(a)
<type 'int'>
>>> a.append(15)
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
a.append(15)
AttributeError: 'int' object has no attribute 'append'
>>> a=[9]
>>> type(a)
<type 'list'>
>>> a.append(15)
>>> a
[9, 15]
EDIT:
Right, now the problem of the scopes. To edit the global int12mmprice put global int12mmprice at the start of the submit function. This makes sure that submit does not look at int12mmprice in its own function scope but in the global scope.
I'm quite new to python I have run into a type error but I personally can't see it. Help will be appreciated. I am using windows 7.
Error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python33\lib\tkinter\__init__.py", line 1475, in __call__
return self.func(*args)
File "C:\Users\Kids\Desktop\Python Tests\Clock2.py", line 18, in mclock
mlable = Label(mGui, str(z), "minute(s) has past.").pack()
TypeError: __init__() takes from 1 to 3 positional arguments but 4 were given
Code:
import sys
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
import os
from time import sleep
def mclock():
x = 1
z = 0
while x != -1:
mlable = Label(mGui,text = "str(x) second(s)").pack()
x = x+1
sleep(1)
if x == 60:
x = 1
z = z+1
mlable = Label(mGui, str(z), "minute(s) has past.").pack()
return
mGui = Tk()
mGui.geometry("300x200+100+100")
mGui.title("Jono's Clock")
menubar = Menu(mGui)
filemenu = Menu(menubar, tearoff = 0)
filemenu.add_command(label = "Clock",command = mclock)
menubar.add_cascade(label = "File",menu = filemenu)
mGui.config(menu = menubar)
mGui.mainloop()
Also if any one knows haw to add a clear function to clear the seconds each time it ticks that will be appreciated as well.
The label initializer, like all Python methods, has a self first arguments. It accepts only up to two additional positional arguments (the master and cfg arguments), but you are giving 3:
Label(mGui, str(z), "minute(s) has past.")
You probably wanted to concatenate those two strings; you'll have to pass this in explicitly as the text keyword argument:
Label(mGui, text=str(z) + " minute(s) has past.")
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.