I am fairly new to Tkinter and I'm trying to code a simple calculator. My problem is no matter what integers I provide the entry widget the sum always returns as zero. Any help would be greatly appreciated.
I have tried making the variables into global variables giving me the same result. I have also tried converting the entry from a StringVar() to int, but this results in a invalid literal error.
(ValueError: invalid literal for int() with base 10: '')
def addRes():
ni1 = int(na1.get())
ni2 = int(na2.get())
result = ni1 + ni2
resAdd = str(result)
Radd = Tk()
Radd.geometry("50x50")
addL = Label(Radd, text= resAdd).pack()
nEadd = Tk()
nEadd.geometry("200x200")
na1 = IntVar()
na2 = IntVar()
numVal1 = Entry(nEadd).place(x=20,y=10)
plusL = Label(nEadd, text= "+").place(x=20,y=30)
numVal2 = Entry(nEadd).place(x=20,y=50)
addResult = partial(addRes)
numSubmit = Button(nEadd, text= "Submit", command = addResult).place(x=40,y=70)
Although you create two IntVars, you don't associate them with an entry so they never change.
You need to change the entries to this:
numVal1 = Entry(nEadd, textvariable=na1).place(x=20,y=10)
numVal2 = Entry(nEadd, textvariable=na2).place(x=20,y=50)
Also, you should not be creating more than one instance of Tk. If you need another window, use Toplevel
I made one program using Python (tkinter). When you click the button "Add Task" new row is created. User needs to enter values in "Size [m2]" and "Total Cost" entries, and when he/she clicks the button "Sum Values", in entry box under cost/m2 should be inserted value "Total Cost"/"Size [m2]" and sum of all values under cost/m2 (sum should be in "answerE")
I made it so that It can sum the values that are entered in entry box under cost/m2, but i cant make it to do the "Total Cost"/"Size [m2]" and to insert that answer under cost/m2 and then sums it. I always get this error:
CostSize=float(CostEntry.get())/float(SizeEntry.get())
NameError: name 'CostEntry' is not defined
And I want this:
What should I do, so that it recognizes the CostEntry?
This is the code:
from tkinter import *
from tkinter import ttk
myApp = Tk()
myApp.title("APP")
myApp.geometry("1000x650")
frame1=LabelFrame(myApp,text=" Activities ")
frame1.grid(row=0,column=0,padx=5)
i=Label(frame1, text=" i ")
i.grid(row=0,column=1)
ProjectName=Label(frame1, text=" Project name ")
ProjectName.grid(row=0,column=2)
SizeLabel=Label(frame1, text="Size [m2]")
SizeLabel.grid(row=0,column=3)
TotalCostLabel=Label(frame1, text="Total Cost")
TotalCostLabel.grid(row=0,column=4)
CostSizeLabel=Label(frame1, text="Cost/m2")
CostSizeLabel.grid(row=0,column=5)
newrow=1
class AddNewTask(object):
rowlist=[]
def update_row_values(self):
for i,entry in enumerate(self.rowlist):
entry.delete(0, 'end')
entry.insert(0,i+1)
def addTask(self):
def delete():
try:
sum = int(answerE.get())
entry_value = int(prodEntry.get())
new_sum = sum - entry_value
answerE.delete(0, 'end')
answerE.insert(0, sum)
except ValueError:
pass
bdelete.destroy()
iEntry.destroy()
ProjectEntry.destroy()
SizeEntry.destroy()
CostEntry.destroy()
CostSizeEntry.destroy()
CostSizeEntry.destroy()
self.rowlist.remove(iEntry)
self.update_row_values()
self.entrylist.remove(CostSizeEntry)
global newrow
newrow=newrow+1
bdelete=Button(frame1,text="-",command=delete)
bdelete.grid(row=newrow,column=0,sticky="E",padx=4)
iEntry=Entry(frame1,width=3)
self.rowlist.append(iEntry)
iEntry.grid(row=newrow,column=1,padx=1)
n = len(self.rowlist)
iEntry.insert(0,n)
ProjectEntry=Entry(frame1,width=75)
ProjectEntry.grid(row=newrow,column=2,padx=1)
SizeEntry=Entry(frame1,width=10)
SizeEntry.grid(row=newrow,column=3,padx=1)
CostEntry=Entry(frame1,width=10)
CostEntry.grid(row=newrow,column=4,padx=1)
CostSizeEntry=Entry(frame1,width=10)
CostSizeEntry.grid(row=newrow,column=5,padx=1)
self.entrylist.append(CostSizeEntry)
def __init__(self):
buttonadd=Button(frame1,text="Add Task",command=self.addTask)
buttonadd.grid(row=0,column=0,padx=3,pady=5)
self.entrylist = []
def sumValues():
try:
CostSize=float(CostEntry.get())/float(SizeEntry.get())
CostSizeEntry.insert(0,CostSize)
except ValueError:
pass
sum = 0
for entry in AddNewTask.entrylist:
try:
sum += float(entry.get())
except ValueError:
pass
answerE.delete(0, 'end')
answerE.insert(0, sum)
sumButton = Button(frame1, text="Sum Values", command=sumValues)
sumButton.grid(row=0, column=7)
AddNewTask=AddNewTask()
frame2=LabelFrame(myApp,text=" Answer")
frame2.grid(row=0,column=1,padx=5,sticky="N")
answerL=Label(frame2, text="Answer: ")
answerL.grid(row=0,column=0)
answerE=Entry(frame2,width=10)
answerE.grid(row=0, column=1)
myApp.mainloop()
The CostEntry variable is created in a class method. However, it is created with local scope. This means that when the method ends, so does the reference to CostEntry. And the next time you call the method (to destroy the object), it doesn't exist.
Solution: Use the self attribute to create an instance of the variable.
self.CostEntry=Entry(frame1,width=10)
self.CostEntry.grid(row=newrow,column=4,padx=1)
and when you go to delete it:
self.CostEntry.destroy()
You should use self attribute with variables that are used out of local scope. Try this:
from tkinter import *
from tkinter import ttk
myApp = Tk()
myApp.title("APP")
myApp.geometry("1000x650")
frame1=LabelFrame(myApp,text=" Activities ")
frame1.grid(row=0,column=0,padx=5)
i=Label(frame1, text=" i ")
i.grid(row=0,column=1)
ProjectName=Label(frame1, text=" Project name ")
ProjectName.grid(row=0,column=2)
SizeLabel=Label(frame1, text="Size [m2]")
SizeLabel.grid(row=0,column=3)
TotalCostLabel=Label(frame1, text="Total Cost")
TotalCostLabel.grid(row=0,column=4)
CostSizeLabel=Label(frame1, text="Cost/m2")
CostSizeLabel.grid(row=0,column=5)
newrow=1
class AddNewTask(object):
rowlist=[]
def update_row_values(self):
for i,entry in enumerate(self.rowlist):
entry.delete(0, 'end')
entry.insert(0,i+1)
def addTask(self):
def delete():
try:
sum = int(answerE.get())
entry_value = int(prodEntry.get())
new_sum = sum - entry_value
answerE.delete(0, 'end')
answerE.insert(0, sum)
except ValueError:
pass
bdelete.destroy()
iEntry.destroy()
ProjectEntry.destroy()
self.SizeEntry.destroy()
self.CostEntry.destroy()
self.CostSizeEntry.destroy()
self.rowlist.remove(iEntry)
self.update_row_values()
self.entrylist.remove(CostSizeEntry)
global newrow
newrow=newrow+1
bdelete=Button(frame1,text="-",command=delete)
bdelete.grid(row=newrow,column=0,sticky="E",padx=4)
iEntry=Entry(frame1,width=3)
self.rowlist.append(iEntry)
iEntry.grid(row=newrow,column=1,padx=1)
n = len(self.rowlist)
iEntry.insert(0,n)
ProjectEntry=Entry(frame1,width=75)
ProjectEntry.grid(row=newrow,column=2,padx=1)
self.SizeEntry=Entry(frame1,width=10)
self.SizeEntry.grid(row=newrow,column=3,padx=1)
self.CostEntry=Entry(frame1,width=10)
self.CostEntry.grid(row=newrow,column=4,padx=1)
self.CostSizeEntry=Entry(frame1,width=10)
self.CostSizeEntry.grid(row=newrow,column=5,padx=1)
self.entrylist.append(self.CostSizeEntry)
def __init__(self):
buttonadd=Button(frame1,text="Add Task",command=self.addTask)
buttonadd.grid(row=0,column=0,padx=3,pady=5)
self.entrylist = []
self.sumButton = Button(frame1, text="Sum Values", command=self.sumValues)
self.sumButton.grid(row=0, column=7)
def sumValues(self):
try:
CostSize=float(self.CostEntry.get())/float(self.SizeEntry.get())
self.CostSizeEntry.insert(0,CostSize)
except ValueError:
pass
sum = 0
for entry in AddNewTask.entrylist:
try:
sum += float(entry.get())
except ValueError:
pass
answerE.delete(0, 'end')
answerE.insert(0, sum)
AddNewTask=AddNewTask()
frame2=LabelFrame(myApp,text=" Answer")
frame2.grid(row=0,column=1,padx=5,sticky="N")
answerL=Label(frame2, text="Answer: ")
answerL.grid(row=0,column=0)
answerE=Entry(frame2,width=10)
answerE.grid(row=0, column=1)
myApp.mainloop()
I have a dynamically created Tkinter checkbutton widget, which takes in the contents of a list of usernames. I then displayed those names with a checkbox alongside.
What I need to do is obviously collect which usernames have been checked, so I can pass that off to another function to action.
How should I write the variable part of this so it creates a new list of chosen usernames?
What I have thus far:
def delprof_results(users_delprof):
for i in range(len(users_delprof)):
c = Checkbutton(resultsFrame, text=users_delprof[i], variable=users_delprof[i])
c.pack(anchor=W)
def delprof_del():
users_chosen = []
print str(users_delprof[i]).get() # Works up until this point. How to get individual variable with ID.
del_but = Button(resultsFrame, text="Delete", width=7, height=1, command=delprof_del)
del_but.pack(side=LEFT)
Thanks in advance,
Chris.
If you want to reach individual objects, simply keep a reference to the individual objects instead of creating objects while overwriting the same variable with each iteration of a loop like:
for i in range(30):
a = i
How to reach a's state where it was 13? Well, you can't as it's overwritten.
Instead, use collection types. In the example below I used dict:
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
except ImportError:
import Tkinter as tk
def upon_select(widget):
print("{}'s value is {}.".format(widget['text'], widget.var.get()))
if __name__ == '__main__':
root = tk.Tk()
names = {"Chester", "James", "Mike"}
username_cbs = dict()
for name in names:
username_cbs[name] = tk.Checkbutton(root, text=name,
onvalue=True, offvalue=False)
username_cbs[name].var = tk.BooleanVar()
username_cbs[name]['variable'] = username_cbs[name].var
username_cbs[name]['command'] = lambda w=username_cbs[name]: \
upon_select(w)
username_cbs[name].pack()
tk.mainloop()
You could make a list of values from the checkbuttons:
values = []
for i in range(len(users_delprof)):
v = IntVar()
c = Checkbutton(master, text="Don't show this again", variable=v)
c.var = v
values.append(v)
Now you can check the value by looking in the list values, and getting the value of a checkbutton with v.get().
I have a list of tkinter entry fields generated dynamically. I need to grab the contents of each field while knowing what it's referring to. I have tried adding something like "entry"+count = Entry(..) but as expected it wont work like that and is really quite a stupid design practice to attempt so I'm thinking it needs to be in the form of an array but can't seem to figure out how to do that with an Entry.
rowNum = 0
items = []
def tableGen(name):
global rowNum
entry = Entry(win).grid(row=rowNum, column=0)
label = Label(win, text=name).grid(row=rowNum, column=1)
self.items[rowNum] = [entry, label] # Problem Area 1
rowNum += 1
def generate(): # Print each items value
for item in items:
print (item.get()) # Problem Area 2
# Generates Entrys and labels from file
e = ET.parse('file.xml').getroot()
for atype in e.findall('things'):
tableGen(atype.get('name'))
generateBtn = Button(root, text="Generate", command=generate).pack()
generate()
root.mainloop()
I've simplifed the code to the minimal required to see what I'm trying to do. The problem seems to be either with where I put the items in a table or try and parse them (problem are 1 & 2). I'm very new to python and can't figure out how to do this. In it's current state the project fails with in tableGen self.items[rowNum] = [entry, label] Name Error: name 'self' is not defined.
Am I doing this wrong? Is there another way this can be done?
Solution
rowNum = 0
items = []
def tableGen(name):
global rowNum
entry = Entry(win)
entry.grid(row=rowNum, column=0)
label = Label(win, text=name)
label.grid(row=rowNum, column=1)
items.append([entry, label])
rowNum += 1
def generate(): # Print each items value
for item in items:
print('Entry:', item[0].get(), 'Label:', item[1].cget("text"))
# Generates Entrys and labels from file
e = ET.parse('file.xml').getroot()
for atype in e.findall('things'):
tableGen(atype.get('name'))
generateBtn = Button(root, text="Generate", command=generate).pack()
generate()
root.mainloop()
Use append() to add items to the end of a list:
def tableGen(name):
...
items.append([entry, label])
rowNum += 1
This will generate a list of lists, so you need to use an index to access the elements of each item:
def generate(): # Print each items value
for item in items:
print('Entry:', item[0].get(), 'Label:', item[1].get())
I am storing a matrix of Entries, each attached to a unique StringVar. On the callback for the StringVar, I want to be able to find which StringVar it was, with respect to the matrix. This is what I have:
def callback(sv, index):
print index
for i in range(ncols):
for j in range(self.nrows):
sv = StringVar()
uniqueId = str(i)+str(j)
sv.trace("w", lambda name, index, mode, sv=sv: callback(sv, uniqueId))
self.results[i][j] = Entry(gridtable,textvariable=sv,bg='grey',borderwidth=1,fg='black',width=self.widget_width).grid(row=j+2,column=i+1,sticky='ew')
However, it always prints the same index ('718' - which is '7'+'18': the values that i and j stop at). How can I get a unique identifier for these StringVars?
The sv variable is changing in your code, but uniqueID is getting stuck at the last value it's given. You can set it to remember its value on that iteration of the loop by including it in the lambda expression, like this:
from Tkinter import *
def callback(var, index):
print var, index
root = Tk()
for i in range(10):
var = StringVar()
uniqueID = i
var.trace('w', lambda name,index,mode, var=var, uniqueID=uniqueID: callback(var, uniqueID))
Entry(root, textvariable=var).pack()
mainloop()