I am trying to create the program that has an add button, When it is clicked, several different elements like entries and buttons should appear on the output window. Firstly I am not able to structure the display correctly and secondly I am not sure as to how to get the values entered by the user in entry widget of Tkinter.
Here is the Code:
from tkinter import *
from tkinter import messagebox
lb = Tk()
def addentry():
i = 3 // the 3 here should keep on incrementing so that the row goes on increasing as the user
keeps on adding different entries. This is for the display
ent1 = Entry(lb, bd=5).grid(row =i ,column= 0)
ent2 = Entry(lb, bd=5).grid(row = i, column=2)
ent3 = Entry(lb, bd=5).grid(row = i, column=4)
ent4 = Entry(lb, bd=5).grid(row = i , column=6)
addent = Button(lb, text = "Add Entry",command = addentry).grid(row = 0, column = 2)
It's all about keepin references. References are used to identify objects.
import tkinter as tk
root = tk.Tk()
my_entries = []
entry_row = 1
def addentry():
global entry_row
ent = tk.Entry(root, bd=5)
ent.grid(row =entry_row ,column= 0)
my_entries.append(ent)
entry_row = entry_row+1
def getter():
for entry in my_entries:
my_stuff = entry.get()
print(my_stuff)
addent = tk.Button(root, text = "Add Entry",command = addentry)
addent.grid(row = 0, column = 0)
getent = tk.Button(root,text='get input', command= getter)
getent.grid(row=0, column=1)
root.mainloop()
In this exampel we keepin the references of the tk.Entry and the variable entry_row while we would like to work with later on. There are a bunch of solution for this. Here we had used a global variable and a list in the global namespace to access them.
Related
Ok, so basic story. I have created an entry. After you introduce text, you have to click a button to store the inputted text into a variable that is later printed.
Here is the code:
from Tkinter import *
def myClick(entry_name, var):#defines function to get input from entry and store into var
var = entry_name.get()
root = Tk()#creates initial tk
lbl1 = Label(root, text = "hello")#before entry label
lbl1.grid(row = 0, column = 0)#label griding
ent = Entry(root, width = 15)# the entry
ent.grid(row = 1, column = 0)#entry gridding
hello = None #variable to store entry input
bt1 = Button(root, command = myClick(ent, hello))#button 1 creation and function attribution
bt1.grid(row = 3, column = 0)#button 1 griding
root.mainloop()
print(hello)
It is very unclear to me why the function does not get the input from the entry.
bt1 = Button(root, command = myClick(ent, hello))
In this line, you call myClick function with parameters, not just pass it. That means that myClick is executed once after the module is launched and then it does nothing. If you want to print the entry input, I recommend you do the following:
from tkinter import *
root = Tk()
lbl1 = Label(root, text="hello")
lbl1.grid(row=0, column=0)
ent = Entry(root, width=15)
ent.grid(row=1, column=0)
def myClick():
var = ent.get()
print(var)
bt1 = Button(root, command=myClick)
bt1.grid(row=3, column=0)
root.mainloop()
Also code after root.mainloop() doesn't excecute.
just define a normal function :
from tkinter import *
def blinta():
var = ent.get()
ent.delete(0,END)
print(var)
root = Tk()#creates initial tk
lbl1 = Label(root, text = "hello")#before entry label
lbl1.grid(row = 0, column = 0)#label griding
ent = Entry(root, width = 15)# the entry
ent.grid(row = 1, column = 0)#entry gridding
bt1 = Button(root, command = blinta)
bt1.grid(row = 3, column = 0)
root.mainloop()
This will work I'm sure.
from tkinter import * // Libraries imported
import tkinter as tk
from tkinter import simpledialog
ROOT = tk.Tk()
strong textROOT.withdraw()
root = Tk()
s=[] //empty list to append entry values
i=0 // to iterate over for loop
for y in range(5):
r= Label(root, text="file_"+str(y)).grid(row=i) //5-labels created using for loop
i=i+1
i=0
for y in range(5):
r=("file_"+str(y)) //5 entry boxes created using for loop
r = Entry(root)
r.grid(row=i , column=1)
i=i+1
def getInput():
for y in range(5): //entry value is stored
r = ("file_"+str(y))
b = r.get()
s.append(b)
root.destroy()
Button(root, text = "submit",command = getInput).grid(row = 5, sticky = W)
//click box 'submit' is created to store values into empty list 's'//
mainloop() //code ends
//The code is showing error : AttributeError: 'str' object has no attribute 'get
//I am not able to store my entry values into an empty list S and later retrieve the entry values of that list.
r = ("file_"+str(y)) followed by b = r.get() won't magically retrieve the contents of the widget. You need to store your Entry widgets in a container like a list.
You could also get rid of the 2nd loop - why don't create both Label and Entry in the same loop?
import tkinter as tk
root = tk.Tk()
entries = []
for y in range(5):
tk.Label(root, text="file_"+str(y)).grid(row=y,column=0)
r = tk.Entry(root)
r.grid(row=y,column=1)
entries.append(r)
def getInput():
print ([ent.get() for ent in entries])
tk.Button(root, text = "submit", command = getInput).grid(row = 5, sticky = "w")
root.mainloop()
I would like to create a function or class that has the proper formatting to create a text label, entry field, and button. The button would allow me to browse through my directory and populate the entry field with the chosen directory. The code I have allows me to do most of this, however the directory is always populated in the last entry field instead of the one the button refers to.
I am new to tkinter and GUIs so apologies if this is a simple solution, I assume the problem is with root.name.set referring to the function that was called last.
from tkinter import *
from tkinter import filedialog
def askdirectory():
dirname = filedialog.askdirectory()
root.name.set(dirname)
def dirField(root, label, rowNum):
text = StringVar()
text.set(label)
dirText = Label(root, textvariable = text, height =4)
dirText.grid(row = rowNum, column = 1)
dirBut = Button(root, text = 'Browse', command = askdirectory)
dirBut.grid(row = rowNum, column = 3)
root.name = StringVar()
adDir = Entry(root,textvariable = root.name, width = 100)
adDir.grid(row = rowNum, column = 2)
if __name__ == '__main__':
root = Tk()
root.geometry('1000x750')
adText = "Select directory of Ads"
userText = "Select directory of User credentials"
adField = dirField(root, adText, 1)
userField = dirField(root, userText, 2)
root.mainloop()
You should realise that you need to have each Entry have its own textvariable. Otherwise they will overlap. Have a look at my code, which should get you going.
from tkinter import *
from tkinter import filedialog
path = [None, None] # Fill it with the required number of filedialogs
def askdirectory(i):
dirname = filedialog.askdirectory()
path[i].set(dirname)
def dirField(root, label, rowNum, i):
dirText = Label(root, text=label)
dirText.grid(row=rowNum, column=0)
dirBut = Button(root, text='Browse', command=lambda: askdirectory(i))
dirBut.grid(row=rowNum, column=2)
path[i] = StringVar()
adDir = Entry(root, textvariable=path[i], width=50)
adDir.grid(row=rowNum, column=1)
if __name__ == '__main__':
root = Tk()
adText = "Select directory of Ads"
userText = "Select directory of User credentials"
adField = dirField(root, adText, 0, 0)
userField = dirField(root, userText, 1, 1)
root.mainloop()
Part of my program prompts the user to enter a sample number into an entry field, and then click a button which generates that number of entry widgets beneath it (to enter information about each sample). The entry widgets appear exactly as expected, one beneath the other for the entered number of samples.
I can't figure out how to separate the variables for each of those new entry widgets now. I had hoped that each one would allow me to enter a different value, and then call them back via .get(). That's not the case, they ALL change together to whatever I type into one. Below is the section of code that I believe is the issue:
normval_f= IntVar()
x= samp.get()
f=1
while f<=x:
f_entry = ttk.Entry(mainframe, width=7, textvariable=normval_f)
f_entry.grid(column=1, row=f+12)
f_label = ttk.Label(mainframe, text="Sample "+str(f)+ " value").grid(column=2, row=f+12, sticky=W)
f=f+1
List and Dictionaries can be very useful when dealing with large amounts or potently large amounts of widgets.
Below is a bit of code to accomplish what you described in your question.
I use a list called self.my_entries to store all the entries that will be created based on the value of what the user types in. I also added a little error handling just in case the user tries to type in something other than a number or nothing is enter when the button is pressed.
The first entry and button are placed on the root window and for all of the entry fields that are going to be created we add a frame below the first button. This will allow us to manage the entry fields a bit easier if we want to reset the field later.
from tkinter import *
class Example(Frame):
def __init__(self):
Frame.__init__(self)
self.pack()
self.my_entries = []
self.entry1 = Entry(self)
self.entry1.grid(row = 0, column = 0)
Button(self, text="Set Entry Fields", command=self.create_entry_fields).grid(row = 1, column = 0)
self.frame2 = Frame(self)
self.frame2.grid(row = 2, column = 0)
def create_entry_fields(self):
x = 0
try:
x = int(self.entry1.get())
if x != 0:
for i in range(x):
self.my_entries.append(Entry(self.frame2))
self.my_entries[i].grid(row=i, column=1)
f_label = Label(self.frame2, text="Label {}: ".format(i+1))
f_label.grid(row=i, column=0)
Button(self.frame2, text="Print to console", command=self.print_all_entries).grid(row=x, column=0, sticky = "nsew")
Button(self.frame2, text="Reset", command=self.clear_frame2).grid(row=x, column=1, sticky = "nsew")
except:
print("Invalid entry. Only numbers are allowed.")
def print_all_entries(self):
for i in self.my_entries:
print(i.get())
def clear_frame2(self):
self.my_entries = []
self.frame2.destroy()
self.frame2 = Frame(self)
self.frame2.grid(row = 2, column = 0)
if __name__ == '__main__':
root = Tk()
test_app = Example()
root.mainloop()
Let me know if you have any questions about the above code.
A few suggestions; don't use a while loop, use a for loop instead. Secondly, I'd suggest storing each of your variables inside a list, or as I have done, in a list. At the moment, you are overwriting your variables each time you go through the loop so you need to create a new one each time and store it somewhere.
Here is an example of storing a number of fields in a dictionary.
from tkinter import *
class App(Frame):
def __init__(self,master):
Frame.__init__(self, master)
fields = ['name','age','gender']
self.field_variables = {}
for idx,field in enumerate(fields):
self.field_variables[field] = StringVar()
f_entry = Entry(self,textvariable=self.field_variables[field])
f_entry.grid(column=2,row=idx)
f_label = Label(self,text=field)
f_label.grid(column=1,row=idx)
go_btn = Button(self,text="Go",command=self.get_all)
go_btn.grid()
def get_all(self):
print(self.field_variables)
if __name__ == '__main__':
root = Tk()
app = App(root)
app.grid()
I want to create a simple GUI where I can enter some values. A label before and at the and an button to start the script.
I was using something like this:
w = Label(master, text="weight:")
w.grid(sticky=E)
w = Label(root, text="bodyfathydrationmuscle:bones")
w.grid(sticky=E)
w = Label(root, text="hydration:")
w.grid(sticky=E)
its ok but i want to do it dynamic. also when i would use w for all the entrys i only could cast w.get once. but i need all my data ;-)
i was thinking of:
def create_widgets(self):
L=["weight","bodyfat","hydration","muscle","bones"]
LV=[]
for index in range(len(L)):
print(index)
print(L[index])
("Entry"+L[index])= Entry(root)
("Entry"+L[index]).grid(sticky=E)
("Label"+L[index])=Label(root, text=L[index])
("Label"+L[index]).grid(row=index, column=1)
To call later:
var_weight=Entryweight.get()
var_bodyfat=Entrybodyfat.get()
and so on. how can i make it work?
Your program suggests that Entrybodyfat and the other variables should be generated on the fly, but you don't want to do that.
The normal approach is to store the entries and labels in a list or a map:
from Tkinter import *
root = Tk()
names = ["weight", "bodyfat", "hydration", "muscle", "bones"]
entry = {}
label = {}
i = 0
for name in names:
e = Entry(root)
e.grid(sticky=E)
entry[name] = e
lb = Label(root, text=name)
lb.grid(row=i, column=1)
label[name] = lb
i += 1
def print_all_entries():
for name in names:
print entry[name].get()
b = Button(root, text="Print all", command=print_all_entries)
b.grid(sticky=S)
mainloop()
The value of the bodyfat entry is then entry["bodyfat"].get().