Unable to store entered Input in Multiple Window in Tkinter - python

I have created multiple windows and i want to print and store data entered in one of the TopLevel windows but it not able to store and print the data. The same thing when Iam doing without multiple windows,Iam able to do that. What can be wrong here, let me know.
from tkinter import *
def Read():
name = namevalue.get()
print('Name:',name)
with open('attendance_data/detail.csv','a+') as f:
f.write(name)
def New():
top1 = Toplevel()
top1.geometry('500x500')
top1.resizable(False,False)
top1.title('Existing Employee Details')
l1 = Label(top1,text='New Employee Registeration',font='comicsans 14 bold',padx=10).grid(row = 0,column=3,pady=50)
name = Label(top1,text='Name',padx=20)
name.grid(row=1,column=2)
namevalue = StringVar()
nameEntry = Entry(top1,textvariable=namevalue).grid(row=1,column=3,pady=25)
Button(top1,text='Submit',command=Read).grid(row=4,column=3,pady=25) # command
top1.mainloop()
root = Tk()
root.geometry('500x500')
root.resizable(False,False)
root.title('Main Window')
l2 = Label(root,text='New Employee Registeration',font='comicsans 14 bold',padx=10).grid(row = 0,column=2,pady=50,padx=50)
b1 = Button(text='New Employee',bg='black',fg='red',font='comicsansms 12 bold',command=New).grid(row=10,column=2,pady=50)
b2 = Button(text='Existing Employee',bg='black',fg='red',font= 'comicsansms 12 bold').grid(row = 11,column=2,pady=50)
root.mainloop()
I am able to print and store the entered data when iam not using Mutiple Windows
from tkinter import *
def Read():
name = namevalue.get()
print('Name:',name)
with open('attendance_data/detail.csv','a+') as f:
f.write(name)
root = Tk()
root.geometry('500x500')
root.resizable(False,False)
root.title('Main Window')
name = Label(root,text='Name',padx=20)
name.grid(row=1,column=2)
namevalue = StringVar()
nameEntry = Entry(root,textvariable=namevalue).grid(row=1,column=3,pady=25)
Button(root,text='Submit',command=Read).grid(row=4,column=3,pady=25) # command
root.mainloop()
Help me in this.

You forgot to add a command to the second button:
b2 = Button(..., command=Read).grid(row = 11,column=2,pady=50)
Thing to note is, you don't have to store the value in variable as the value of b2 is None, so you might as well remove the variable.
Edit:
You need to make the entry, namevalue, a global variable so it can be accessed outside New and inside Read and other functions.
def New():
global namevalue
....

Related

How to get the value of an Entry created in a def?

I'm working on a project and i would like to get the Value of an Entry created in a def (turned on by a button on Tkinter)
So I have my main tkinter menu, with a button which will call the def "panier".
The def "panier" is creating the Entry "value" and another button to call a second def "calcul".
The second def "calcul" will do things with the value of Entry...
But then, in the def "calcul", when i'm trying to do value.get() it tells "NameError: name 'value' is not defined"
Here is the code, btw the Entry must be created by the def...
from tkinter import *
def panier():
value=Entry(test)
value.pack()
t2=Button(test,text="Validate",command=calcul)
t2.pack()
def calcul(value):
a=value.get()
#here will be the different calculations I'll do
test=Tk()
t1=Button(test,text="Button",command=panier)
t1.pack()
test.mainloop()
Appreciate every feedback :)
You can make the variable global like this:
from tkinter import *
def panier():
global value
value = Entry(test)
value.pack()
t2 = Button(test, text="Validate", command=calcul)
t2.pack()
def calcul():
a = value.get()
print(a)
#here will be the different calculations I'll do
test = Tk()
t1 = Button(test, text="Button", command=panier)
t1.pack()
test.mainloop()
The global value line makes the variable global so you can use it anywhere in your program.
You can also pass in the variable as an argument like what #JacksonPro suggested
t2 = Button(test, text="Validate", command=lambda: calcul(value))
This is one way to do it. Globally create a collection (list or dictionary) to hold a reference to the Entry. When you create the Entry, add it to the collection. I made it with either a list or dictionary for holding the references, so toggle the commented variations in all three places to try it both ways.
import tkinter as tk
def panier():
for item in ('value', ):
ent = tk.Entry(test)
collection.append(ent)
# collection[item] = ent
ent.pack()
t2 = tk.Button(test,text="Validate",command=calcul)
t2.pack()
def calcul():
a = collection[0].get()
# a = collection['value'].get()
print(a)
collection = []
# collection = {}
test = tk.Tk()
t1 = tk.Button(test, text="Button", command=panier)
t1.pack()
test.mainloop()

Retrieving value from Tkinter combobox

Eventually I want to use the values in the comboboxes as parameters in other functions, but I think if I can just get them to print for now, that will be enough to build off of. Here's what I have so far.
import tkinter as tk
from tkinter import ttk
import time
def ok():
betType = betTypeVar.get()
season = seasonVar.get()
print(betType, season)
def CreateSimPreviousSeasonWindow():
prevSeasonWindow = tk.Tk()
#============= Bet Type Input =============#
betTypeVar = tk.StringVar()
betTypeLabel = tk.Label(prevSeasonWindow, text="Bet type:").grid(row=0,column=0)
betTypeChosen = ttk.Combobox(prevSeasonWindow, values=['Moneyline','Total'])
betTypeChosen.grid(row=0, column=1)
seasonVar = tk.StringVar()
seasonLabel = tk.Label(prevSeasonWindow, text='Season:').grid(row=1, column=0)
seasonChosen = ttk.Combobox(prevSeasonWindow, values=['2018', '2017'])
seasonChosen.grid(row=1,column=1)
button = tk.Button(prevSeasonWindow, text='OK', command=ok)
button.grid(row=2,column=0)
prevSeasonWindow.mainloop()
This gives me
File "C:[directory...]", line 6, in ok
betType = betTypeVar.get()
NameError: name 'betTypeVar' is not defined
To me it looks pretty obvious that this error is because ok() doesn't have any parameters passed to it, so it has no idea what 'betTypeVar' is, but all the tutorials I've read do it this way, so I'm missing something. If I try actually passing ok() the arguments, it still doesn't work.
There are two things to fix in your code. First let's focus on CreateSimPreviousSeasonWindow:
betTypeVar = tk.StringVar()
seasonVar = tk.StringVar()
You defined two StringVar but you actually never used it or linked them to your combobox object. The correct way is to set them as a textvaraible:
betTypeChosen = ttk.Combobox(prevSeasonWindow, textvariable=betTypeVar, values=['Moneyline','Total'])
seasonChosen = ttk.Combobox(prevSeasonWindow, textvariable=seasonVar, values=['2018', '2017'])
Next, NameError: name 'betTypeVar' is not defined is due to your variables being local variables. You are trying to access the same variable across different functions. To pass them around, you need to declare global:
def ok():
global betTypeVar, seasonVar
betType = betTypeVar.get()
season = seasonVar.get()
print(betType, season)
def CreateSimPreviousSeasonWindow():
global betTypeVar, seasonVar
...
Also I want to point out that if you just want to retrieve the values of the combobox, you don't really need to create two StringVar. Just combobox.get() already works good enough.
import tkinter as tk
from tkinter import ttk
import time
def ok():
global betTypeChosen, seasonChosen
print (betTypeChosen.get(), seasonChosen.get())
def CreateSimPreviousSeasonWindow():
global betTypeChosen,seasonChosen
prevSeasonWindow = tk.Tk()
#============= Bet Type Input =============#
betTypeLabel = tk.Label(prevSeasonWindow, text="Bet type:").grid(row=0,column=0)
betTypeChosen = ttk.Combobox(prevSeasonWindow,values=['Moneyline','Total'])
betTypeChosen.grid(row=0, column=1)
seasonLabel = tk.Label(prevSeasonWindow, text='Season:').grid(row=1, column=0)
seasonChosen = ttk.Combobox(prevSeasonWindow, values=['2018', '2017'])
seasonChosen.grid(row=1,column=1)
button = tk.Button(prevSeasonWindow, text='OK', command=ok)
button.grid(row=2,column=0)
prevSeasonWindow.mainloop()
CreateSimPreviousSeasonWindow()

Need to track variables from multiple Tkinter checkboxes

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().

How to make expressions in Tkinter Python

I'm new in python programming and I'm having some issues in developing a specific part of my GUI with Tkinter.
What I'm trying to do is, a space where the user could enter (type) his math equation and the software make the calculation with the variables previously calculated.
I've found a lot of calculators for Tkinter, but none of then is what I'm looking for. And I don't have much experience with classes definitions.
I made this simple layout to explain better what I want to do:
import tkinter as tk
root = tk.Tk()
Iflabel = tk.Label(root, text = "If...")
Iflabel.pack()
IfEntry = tk.Entry(root)
IfEntry.pack()
thenlabel = tk.Label(root, text = "Then...")
thenEntry = tk.Entry(root)
thenlabel.pack()
thenEntry.pack()
elselabel = tk.Label(root, text = "else..")
elseEntry = tk.Entry(root)
elselabel.pack()
elseEntry.pack()
applybutton = tk.Button(root, text = "Calculate")
applybutton.pack()
root.mainloop()
This simple code for Python 3 have 3 Entry spaces
1st) If...
2nd Then...
3rd) Else...
So, the user will enter with his conditional expression and the software will do the job. In my mind, another important thing is if the user left the "if" space in blank, he will just type his expression inside "Then..." Entry and press the button "calculate" or build all expression with the statements.
If someone could give some ideas about how and what to do....
(without classes, if it is possible)
I'l give some situations for exemplification
1st using statements:
var = the variable previously calculated and stored in the script
out = output
if var >= 10
then out = 4
else out = 2
2nd Without using statement the user will type in "Then" Entry the expression that he want to calculate and that would be:
Then: Out = (((var)**2) +(2*var))**(1/2)
Again, it's just for exemplification...I don't need this specific layout. If anyone has an idea how to construct it better, is welcome.
Thanks all.
Here is a simple version of what you are trying to do.
We need to use the eval built in function to evaluate the math of a string.
We should also write our code with some error handling as there is a very good change a user will type a formula wrong and the eval statement will fail.
For more information on eval and exec take a look at this post here. I think it does a good job of explaining the two.
Here is what it would look like:
import tkinter as tk
root = tk.Tk()
math_label = tk.Label(root, text = "Type formula and press the Calculate button.")
math_label.pack()
math_entry = tk.Entry(root)
math_entry.pack()
result_label = tk.Label(root, text = "Results: ")
result_label.pack(side = "bottom")
def perform_calc():
global result_label
try:
result = eval(math_entry.get())
result_label.config(text = "Results: {}".format(result))
except:
result_label.config(text = "Bad formula, try again.")
applybutton = tk.Button(root, text = "Calculate", command = perform_calc)
applybutton.pack()
root.mainloop()
The first answer gets at the right thought, but it can also be matched a little more explicitly to the example you gave, in case you want to take this a little further.
Basically you want to use the eval statement to test your conditional, and then use the exec statement to run your python code blocks. You have to pass in the globals() argument in order to make sure your exec functions modify the correct variables in this case
See below:
import tkinter as tk
from tkinter import messagebox
var = 10
out = 0
def calculate():
global out
try:
if eval(IfEntry.get()):
exec(thenEntry.get(), globals())
else:
exec(elseEntry.get(), globals())
messagebox.showinfo(title="Calculation", message="out: " + str(out))
except:
exc_type, exc_value, exc_traceback = sys.exc_info()
msg = traceback.format_exception(exc_type, exc_value, exc_traceback)
messagebox.showinfo("Bad Entry", message=msg)
root = tk.Tk()
Iflabel = tk.Label(root, text = "If...")
Iflabel.pack()
IfEntry = tk.Entry(root)
IfEntry.insert(0, "var >= 10")
IfEntry.pack()
thenlabel = tk.Label(root, text = "Then...")
thenEntry = tk.Entry(root)
thenlabel.pack()
thenEntry.insert(0, "out = 4")
thenEntry.pack()
elselabel = tk.Label(root, text = "else..")
elseEntry = tk.Entry(root)
elselabel.pack()
elseEntry.insert(0, "out = 2")
elseEntry.pack()
applybutton = tk.Button(root, command=calculate, text = "Calculate")
applybutton.pack()
applybutton.focus_displayof
root.mainloop()

Global variables and appending for use in other top level functions

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.

Categories