I have written a code where Label and Entry widgets' variables are put in a list (in order to avoid the number of lines which will take for creation of each Label and Entry widgets). Then a for loop to create Label and Entry widgets are used, A submit button is used which have to list the entries of each Entry widget. But an empty value is displayed instead of displaying the entered value. Can anyone help me to know the reason and correct the code.
Below is the code which I have written:
from Tkinter import *
app = Tk()
list1 = ['l1','l2','l3']
list2 = ['e1','e2','e3']
entries = []
r = 0
c = 0
for m,n in zip(list1, list2):
x = Label(app, text=m)
x.grid(row = r, column =c)
n = StringVar()
e = Entry(app, textvariable = n)
e.grid(row =r , column = c+1)
entries.append(e.get())
r = r + 1
def func():
entries.append("Dfg")
print entries
s = Button(app, text = "Submit", command = func)
s.grid(row = r, columnspan=2)
app.minsize(400, 400)
app.mainloop()
Please note: There could be indentation problem while posting the code, sorry for the inconvenience.
The for loop is for initialize in this case, When the Entry is been created,The input of Entry is empty , so when you entries.append(e.get()) got the empty
.I change something from your code , and the entries will be entered value when you click the button BTW I use python3 instead of python2
from tkinter import *
app = Tk()
list1 = ['l1','l2','l3']
list2 = ['e1','e2','e3']
entries = []
e = []
r = 0
c = 0
for index, m in enumerate(zip(list1, list2)):
x = Label(app, text=m)
x.grid(row = r, column =c)
n = StringVar()
e.append( Entry(app, textvariable = n))
e[index].grid(row =r , column = c+1)
r = r + 1
def func():
entries = []
for a in e:
entries.append(a.get())
print(entries)
s = Button(app, text = "Submit", command = func)
s.grid(row = r, columnspan=2)
app.minsize(400, 400)
app.mainloop()
Related
Why is this not working? On button click it should add 1.
from tkinter import *
root = Tk()
m = 0
def clicka(m):
m = m + 1
lbl = Label(text=str(m)).place(relx=0.1, rely = 0.2)
exe = Button(text = '↵', bg = 'black', fg = 'red',command=clicka(m), relief='flat').place(relx=0.19, rely = 0.32)
lbl = Label(text=str(m)).place(relx=0.1, rely = 0.2)
root.mainloop()
There are issues in your code:
command=clicka(m) will execute clicka(m) immediately and assign the result of clicka(m) (which is None) to command option. So nothing will be done when the button is clicked later.
passing variable of primitive type will be passed by value, so even it is modified inside the function, the original variable will not be updated.
I would suggest to change m to IntVar and associate it to lbl via textvariable option, then updating m will update lbl at once:
import tkinter as tk
root = tk.Tk()
def clicka():
m.set(m.get()+1)
tk.Button(text='↵', bg='black', fg='red', command=clicka, relief='flat').place(relx=0.19, rely = 0.32)
m = tk.IntVar(value=0)
tk.Label(textvariable=m).place(relx=0.1, rely = 0.2)
root.mainloop()
You could try to set the variable m as global
from tkinter import *
root = Tk()
m = 0
def clicka():
global m
m = m + 1
lbl = Label(text=str(m)).place(relx=0.1, rely = 0.2)
print('Hi')
exe = Button(text = '↵', bg = 'black', fg = 'red',command=clicka, relief='flat').place(relx=0.19, rely = 0.32)
lbl = Label(text=str(m)).place(relx=0.1, rely = 0.2)
root.mainloop()
Indeed like #acw1668 mentioned, you can work with lambda or you can just use global.
This is much shorter.
from tkinter import *
root = Tk()
m = 0
def clicka():
global m
m += 1
lbl["text"] = str(m)
exe = Button(text='↵', bg='black', fg='red', command=clicka, relief='flat')
exe.place(relx=0.19, rely=0.32)
lbl = Label(text=str(m))
lbl.place(relx=0.1, rely=0.2)
root.mainloop()
You could try this :
from tkinter import *
win = Tk()
myvar = IntVar()
def Adder():
k = int(myvar.get())
k = k + 1
lb.insert(1 , k)
win.geometry("750x750")
l1 = Label(win , text = "Number")
l1.grid(row = 0 , column = 0)
e1 = Entry(win , textvariable = myvar)
e1.grid(row = 1 , column = 0)
b = Button(win , command = Adder)
b.grid(row = 2 , column = 0)
lb = Listbox(win , width = 20)
lb.grid(row = 3 , column = 0)
win.mainloop()
well this is the real code!!!
first of all , this question is just about add one number to 1 ;
so our function (you could use lambda function too) could place in the main statements but , how it's work ? in tkinter module , the variables must be define with the Reserved words like StringVar and IntVar. second if you wondering why i put
lb.insert(1,k)
in the function and how it works ? i have to say this "lb" variable, is a global variable in all part of the program, from the beginning to the end, and the Adder function can use it too , besides if you put (lb) variable beneath the
lb.grid(row =3 , column = 0)
lb.insert(1 , Adder())
Adder just calculate the amount of variable but insert method can't show the result (insert method doesn't have this).
I hope it was helpful.
I have used a loop to turn a list of 4 values into a set of buttons. I need to overwrite the text of these buttons to contain the values of another list (in this case Ans2). any help would be greatly appreciated.
import tkinter as tk
root = tk.Tk()
def NextQuestion():
print("this is where i need to configure the buttons to contain values from list - Ans2")
Ans1 = [6,5,32,7]
Ans2 = [4,9,3,75]
AnsNo = 0
r = 0
c = 0
for x in range(len(Ans1)):
AnsBtn = tk.Button(root, text=(Ans1[AnsNo]), command = NextQuestion)
AnsBtn.grid(row=r, column=c)
AnsNo = AnsNo+1
if r == 1:
c = 1
r = 0
else:
r = r+1
First you need to store the buttons somewhere so they can be accessed to be changed. Then you just access their text variable and change it.
import tkinter as tk
root = tk.Tk()
def NextQuestion():
for i, button in enumerate(buttons):
button["text"] = Ans2[i]
Ans1 = [6,5,32,7]
Ans2 = [4,9,3,75]
buttons = []
AnsNo = 0
r = 0
c = 0
for i,answer in enumerate(Ans1):
AnsBtn = tk.Button(root, text=(answer), command = NextQuestion)
AnsBtn.grid(row=r, column=c)
buttons.append(AnsBtn)
if r == 1:
c = 1
r = 0
else:
r = r+1
root.mainloop()
I've been making a script for checking grammar. Now I've updated it to be in a gui using Tkinter. The problem is that I'm trying to indicate the row where the grammar is wrong, and when I use an entry field to input the text everything is in one row.
My question is how do you expand the entry field?
This is my code:
import re
from tkinter import *
window = Tk()
window.minsize(width=300, height= 20)
wr = []
def work():
x = e1.get()
print(x)
BigLetterSearcher = re.compile(r'\. .|\n')
mo = BigLetterSearcher.findall(e1.get())
x = 1
y = 0
v = 0
z = ""
wr = []
for i in mo:
if i == '\n':
x += 1
elif i != i.upper():
v = 1
if x != y:
z = "Row", x
wr.append(z)
wr.append(i)
y = x
if v == 0:
wr.append ("Congratulations none of your grammar was wrong!")
l1.configure(text=wr)
l1 = Label(window, text="example")
e1 = Entry(window, text="Enter text here: ")
b1 = Button(window, text="Work", command=work)
leb = [l1, e1, b1]
for all in leb:
all.pack()
window.mainloop()
The entry widget is not capable of being expanded vertically. This is because there is already a widget designed for this and that is called Text(). For adding text to the text widget we can use insert() and you specify where with a 2 part index. The first part is the row and the 2nd is the column. For the row/line it starts at number 1 and for the index of that row it starts at zero.
For example if you wish to insert something at the very first row/column you would do insert("1.0", "some data here").
Here is you code with the use of Text() instead.
import re
from tkinter import *
window = Tk()
window.minsize(width=300, height= 20)
wr = []
def work():
x = e1.get("1.0", "end-1c")
print(x)
BigLetterSearcher = re.compile(r'\. .|\n')
mo = BigLetterSearcher.findall(x)
x = 1
y = 0
v = 0
z = ""
wr = []
for i in mo:
if i == '\n':
x += 1
elif i != i.upper():
v = 1
if x != y:
z = "Row", x
wr.append(z)
wr.append(i)
y = x
if v == 0:
wr.append ("Congratulations none of your grammar was wrong!")
l1.configure(text=wr)
l1 = Label(window, text="example")
e1 = Text(window, width=20, height=3)
e1.insert("end", "Enter text here: ")
b1 = Button(window, text="Work", command=work)
leb = [l1, e1, b1]
for all in leb:
all.pack()
window.mainloop()
Expanding an Entry field vertically can only be done by changing the size of the font associated with the Entry field...
e1 = Entry(window, text="Enter text here: ", font=('Ubuntu', 24))
results in a taller Entry field than
e1 = Entry(window, text="Enter text here: ", font=('Ubuntu', 12))
I'm trying to create multiple entry boxes with a for loop, so i don't have to make all the different boxes manually in case i want to increase the amount of entries, but this way I can't get my entry value via .get(). If i print L1 the output is a list of three empty strings, so no value was added after I typed them into the entry boxes. How can I make a list containing all the entry values as floats?
from tkinter import *
window = Tk()
window.geometry("450x450+200+200")
def do():
print(L1)
L1 = []
for i in range(3):
labelx = Label(window, text = str(i)).grid(row = i, column = 0)
v = StringVar()
num = Entry(window, textvariable = v).grid(row = i, column = 1)
num1 = v.get()
L1.append(num1)
button1 = Button(window, text = 'OK', command = do).grid(column = 1)
Your original code is storing the value in a list. Instead, store a reference to the widget. With this, there's no reason to create the StringVar objects.
Note that to do this you must create the widget and call grid as two separate statements. It not only allows this technique to work, it's generally considered a best practice to separate widget creation from widget layout.
L1 = []
for i in range(3):
labelx = Label(window, text = str(i))
num = Entry(window, textvariable = v)
labelx.grid(row = i, column = 0)
num.grid(row = i, column = 1)
L1.append(num)
...
for widget in L1:
print("the value is", widget.get())
Use the list, L1, to store the id of the Tkinter StringVar(). Use the get method in the function called by the button. Otherwise, how is the program to know when the data is ready to be retrieved. A StringVar returns a string that will have to be converted to a float. Also, it's a bad habit to use i, l, or o as single digit variable names as they can look like numbers.
window = Tk()
window.geometry("450x450+200+200")
def do():
for var_id in L1:
print(var_id.get())
var_id.set("")
L1 = []
for ctr in range(3):
## grid() returns None
Label(window, text = str(ctr)).grid(row = ctr, column = 0)
var_id = StringVar()
ent=Entry(window, textvariable = var_id)
ent.grid(row = ctr, column = 1)
##num1 = v.get()-->nothing entered when program starts
if 0==ctr:
ent.focus_set()
L1.append(var_id)
button1 = Button(window, text = 'OK', command = do).grid(column = 1)
window.mainloop()
I started making a function that when a selection in a listbox is double clicked, the selection info(a dictionary) gets returned.
def OnDouble(self, event):
widget = event.widget
selection = widget.curselection()
value = widget.get(selection[0])
What I want is to be able to take that selection that gets returned and edit it's contents. By doing this, any changes in content should show up in the listbox and the list from which it comes from.
Example of value that gets returned with double click:
{'Num Tel/Cel': 'test1', 'Email': 'test1', 'Fecha de Entrega': '', 'Orden Creada:': ' Tuesday, June 23, 2015', 'Nombre': 'test1', 'Num Orden': '1'}
from Tkinter import *
oneThing = {"Name:": "Guido", "Tel.:":"666-6969", "Email:":"foobar#lol.com"}
another = {"Name:": "Philler", "Tel.:":"111-1111", "Email:":"philler#lol.com"}
z = [oneThing, another]
root = Tk()
l = Listbox(root)
l.pack(fill = "both")
l.pack_propagate(True)
[l.insert(END, item) for item in z]
def createPerson(index):
#This is whatever function that creates stuff
def edit():
for i in range(len(labels)):
z[index][labels[i]] = entries[i].get()
print z
top.destroy()
top = Toplevel()
labels = ["Name:", "Tel.:", "Email:"]
i = 0
for text in labels:
Label(top, text = text).grid(column = 0, row = i)
i += 1
e1 = Entry(top)
e1.grid(column = 1, row = 0)
e2 = Entry(top)
e2.grid(column = 1, row = 1)
e3 = Entry(top)
e3.grid(column = 1, row = 2)
Button(top, text = "Submit", command = edit).grid(column = 1, row = 3)
entries = [e1, e2, e3]
#Return reference to toplevel so that root can wait for it to run its course
return top
def edit():
global l, z, root
# Get dictionary from listbox
sel = l.curselection()
if len(sel) > 0:
indexToEdit = z.index(eval(l.get(sel[0])))
l.delete(sel)
root.wait_window(createPerson(indexToEdit))
print z[indexToEdit]
l.insert(sel, z[indexToEdit])
Button(root, text = "Edit", command = edit).pack()
root.mainloop()
Edit: Example now shows a way to edit elements on the fly based on user input; uses Toplevel() widget to accept input.
You can use the functions given in this documentation for editing the selections of a listbox.
Example -
widget.selection_set(<item to add>) # adds an item to the selection
or
widget.selection_clear(<item to remove>) # removes the item from the selection
Documentation for selection_set - here
Documentation for selection_clear - here