I have a GUI with a x-number of entries. I want the output to be like a list of all the entries. I have the following code:
from Tkinter import *
master = Tk()
lijst=[]
x=0
while x<3:
a="e"+str(x)
lijst.append(a)
x=x+1
x=0
labels=[]
x=1
while x<4:
a="File"+str(x)+":"
labels.append(a)
x=x+1
x=0
while x<3:
a=labels[x]
b=Label(master,text=a)
b.grid(row=x+1, column=0)
x=x+1
x=0
while x<3:
a=lijst[x]
b=Entry(master)
b.grid(row=x+1, column=1)
c=Label(master, text=".txt ")
c.grid(row=x+1, column=1,sticky=E)
x=x+1
Button(master, text='Enter', command=???,width=20).grid(row=4, column=2, sticky=W, pady=4,padx=20)
mainloop()
output: list=[e0.get(),e1.get(),etc...
How can i create a list that looks like output and does not depend on the number of entries?
You can create the list of entries more easily using a comprehension list:
entries = [Entry(master) for i in range(3)]
for i, entry in enumerate(entries):
label_text = "File%s:" % (i+1)
Label(master, text=label_text).grid(row=i, column=0)
entry.grid(row=i, column=1)
Label(master, text=".txt").grid(row=i, column=2, padx=(0, 15))
Once thit list is created, print the get() call of each entry is trivial:
def print_entries():
print [entry.get() for entry in entries]
Button(master, text='Enter', width=20, command=print_entries).grid(row=4, column=3, sticky=W, pady=4,padx=20)
I have replaced the trailing withespaces of the ".txt" string with right padding as explained here, which is more clear.
Related
I have two functions that create X number of entry widgets based on the number a user inputted:
def Pap_geo():
num_Pap = int(Pap.get())
Pap_GEOs = []
for i in range(num_Pap):
gt_geo = Entry(top, width=20)
gt_geo.focus_set()
gt_geo.grid(row=2+i, column=0, padx=20, pady=0, sticky="W")
Pap_GEOs.append(gt_geo)
return Pap_GEOs
and:
def Sap_geo():
num_Sap = int(Sap.get())
Sap_GEOs = []
for i in range(num_Sap):
Sap_geo = Entry(top, width=20)
Sap_geo.focus_set()
Sap_geo.grid(row=2 + i, column=1, padx=20, pady=0, sticky="W")
Sap_GEOs.append(Sap_geo)
return Sap_GEOs
I want to be able to click 'ok' and print the results of these two lists. I've gotten as far as:
def save():
Pap_GEOs2 = []
for j in Pap_geo():
Pap_GEOs2.append(j.get())
print(Pap_GEOs2)
Sap_GEOs2 = []
for j in Sap_geo():
Sap_GEOs2.append(j.get())
print(Sap_GEOs2)
button = Button(top, text="Save", command=save)
button.grid(row=1, column=1, padx=(170, 0), pady=(0, 10), sticky="W")
This prints two lists of the correct length, however they are empty. I had a similar question before, which was resolved. The solution was to create a list of the entry widgets then call get() on each of those widgets in the OK function. I thought that's what I was doing here but I am getting the same issue. Any input would be appreciated.
Thank you
Hello im having python learning project. I want to insert in GUI two numbers, which are defining range for program to generate random number from.
I am really having problems with calling function with press of the button. And constantly getting error ValueError: invalid literal for int() with base 10: '', when trying to convert string from entry in GUI to int and then inserting them into random.randint.
Thx for Help!
from tkinter import *
import random
root = Tk()
root.title("Generator custom random number")
#function that gets number from entry converts string to int and defines target number in stevilo
def function():
string_answer1 = prvo_stevilo.get()
int1 = int(string_answer1)
string_answer2 = drugo_stevilo.get()
int2 = int(string_answer2)
stevilo = random.randint(int1, int2)
#Defining GUI
navodilo = Label(root, text="Choose custom lower and upper number to chose random number from", width=60)
navodilo2 = Label(root, text="From", width=20, borderwidth=3)
navodilo3 = Label(root, text="To", width=20, borderwidth=3)
prvo_stevilo = Entry(root, width=20, borderwidth=3)
drugo_stevilo = Entry(root, width=20, borderwidth=3)
gumb = Button(root, text="Generate number", width=17, height=2, command=function)
praznavrstica = Label(root, text="")
izpis = Label(root, text="Random number is: ", width=20)
izpis_stevila = Label(root, text="" + stevilo)
#Showcase of gui
navodilo.grid(row=0, column=0, columnspan=1)
navodilo2.grid(row=1, column=0, columnspan=1)
navodilo3.grid(row=3, column=0, columnspan=1)
prvo_stevilo.grid(row=2, column=0, columnspan=1)
drugo_stevilo.grid(row=4, column=0, columnspan=1)
praznavrstica.grid(row=5, column=0, columnspan=1)
gumb.grid(row=6, column=0, columnspan=1)
praznavrstica.grid(row=7, column=0, columnspan=1)
izpis.grid(row=8, column=0, columnspan=1)
izpis_stevila.grid(row=9, column=0, columnspan=1)
#Loop
root.mainloop()
I've noticed few problems with your code. I was able to make it running without too many changes, although probably it is not the best way.
First answer to your question: you are getting this error, because you are trying to change string -> '' to int. It happens because function() is running before you click button.
Another problem:
izpis_stevila = Label(root, text="" + stevilo)
variable 'stevilo' simply doesn't exist before calling function(), so delete it from here.
My proposition for changes:
1)
gumb = Button(root, text="Generate number", width=17, height=2,command = lambda: function())
Without lambda your function will run no matter of state of your button.
2)
first = IntVar(root, value=0)
second = IntVar(root, value=1)
prvo_stevilo = Entry(root, width=20, borderwidth=3, textvariable=first)
drugo_stevilo = Entry(root, width=20, borderwidth=3, textvariable=second)
If you run function without any values in your entry you will get error. This change allows you to put default value for your entry widgets.
3)
def function():
if prvo_stevilo.get() == '' or drugo_stevilo.get() =='':
return
else:
string_answer1 = prvo_stevilo.get()
int1 = int(string_answer1)
string_answer2 = drugo_stevilo.get()
int2 = int(string_answer2)
stevilo = random.randint(int1, int2)
izpis_stevila = Label(root, text=str(stevilo))
izpis_stevila.grid(row=9, column=0)
Firstly check if your entry is not empty.
Secondly update label, also remeber about changing int to string here text=str(stevilo).
I'm trying to create a sudoku solver. I have my grid with the entries at this point but I don't know how to get the values that the user has put in them.
I have no clue yet as to how I'm going to make the Sudoku solver but I think I'll first have to find a way to store the input in some variable(s) so I can work with them later on.
So my question is, how do I get the values that have been filled into the entries?
This is my code thus far:
from tkinter import *
root = Tk()
root.title('Sudoku Solver')
root.geometry('500x400')
mylabel = Label(root, text='Fill in the numbers and click solve').grid(row=0, column=0, columnspan=10)
# Create the grid
def beg():
global e
cells = {}
for row in range(1, 10):
for column in range(1, 10):
if ((row in (1,2,3,7,8,9) and column in (4,5,6)) or (row in (4,5,6) and column in (1,2,3,7,8,9))):
kleur='black'
else:
kleur='white'
cell = Frame(root, bg='white', highlightbackground=kleur,
highlightcolor=kleur, highlightthickness=2,
width=50, height=50, padx=3, pady=3, background='black')
cell.grid(row=row, column=column)
cells[(row, column)] = cell
e = Entry(cells[row, column], width=4, bg='white', highlightthickness=0, fg='black', relief=SUNKEN)
e.pack()
# Tell the button what to do
def solve():
global e
test = e.get()
print(test)
# Create the buttons and give them a command
clearer = Button(root, text='Clear', command=beg)
solver = Button(root, text='Solve', command=solve)
# Locate the buttons
clearer.grid(row=11, column=3, pady=30)
solver.grid(row=11, column=7, pady=30)
# Run it for the first time
beg()
root.mainloop()
I also tried changing e to e[row, column] but that gave me a syntax error.
Standard rule: if you have many elements then keep them on list or dictionary.
Do the same as with cells
Create dictionary
entries = {}
add to dictionary
entries[(row, column)] = e
and get from dictionary
def solve():
for row in range(1, 10):
for column in range(1, 10):
print(row, column, entries[(row, column)].get() )
# from tkinter import * # PEP8: `import *` is not preferred
import tkinter as tk
# --- functions ---
# Create the grid
def beg():
# remove old widgets before creating new ones
for key, val in cells.items():
print(key, val)
val.destroy()
for row in range(1, 10):
for column in range(1, 10):
if ((row in (1,2,3,7,8,9) and column in (4,5,6)) or (row in (4,5,6) and column in (1,2,3,7,8,9))):
kleur='black'
else:
kleur='white'
cell = tk.Frame(root, bg='white', highlightbackground=kleur,
highlightcolor=kleur, highlightthickness=2,
width=50, height=50, padx=3, pady=3, background='black')
cell.grid(row=row, column=column)
cells[(row, column)] = cell
e = tk.Entry(cell, width=4, bg='white', highlightthickness=0, fg='black', relief='sunken')
e.pack()
entries[(row, column)] = e
# Tell the button what to do
def solve():
for row in range(1, 10):
for column in range(1, 10):
print(row, column, entries[(row, column)].get() )
# --- main ---
entries = {}
cells = {}
root = tk.Tk()
root.title('Sudoku Solver')
root.geometry('500x400')
mylabel = tk.Label(root, text='Fill in the numbers and click solve')
mylabel.grid(row=0, column=0, columnspan=10)
# Create the buttons and give them a command
clearer = tk.Button(root, text='Clear', command=beg)
solver = tk.Button(root, text='Solve', command=solve)
# Locate the buttons
clearer.grid(row=11, column=2, pady=30, columnspan=3) # I added `columnspan=3`
solver.grid(row=11, column=6, pady=30, columnspan=3) # I added `columnspan=3`
# Run it for the first time
beg()
root.mainloop()
I have spent some time updating my code. I am trying to create a tool which returns acronyms. I have created separate dictionaries for each letter of the alphabet and have created a result box to return what the acronym stands for. However when running the code I can only get the latest dictionary to return a result i.e. any acronyms in the 'c' dictionary, and each time I add a new dictionary I lose the function of the previous. I am quite new to coding and I have done a lot of research of previous questions before asking this, so any help would be much appreciated. Thanks. This is the code I have so far:
from tkinter import*
acronym_dictionary={"A":"Annual", "AC":"Air Conditioning",
}
acronym_dictionary_b={"BA":"British Airway", "BB":"BumbleBee",
}
acronym_dictionary_c={"Ca":"Calcium","Co":"Company",
}
def Return_Entry(en):
content= entry.get()
result= acronym_dictionary.get(content, "Not found")
print(result)
resultBox.delete(0,END)
resultBox.insert(0,result)
def Return_EntryB(en):
content= entry.get()
result= acronym_dictionary_b.get(content, "Not found")
print(result)
resultBox.delete(0,END)
resultBox.insert(0,result)`
def Return_EntryC(en):
content= entry.get()
result= acronym_dictionary_c.get(content, "Not found")
print(result)
resultBox.delete(0,END)
resultBox.insert(0,result)
def EntryDel():
resultBox.delete(0,END)
entry.delete(0,END)
master=Tk()
master.title("The Acronym Search Engine")
master.geometry('500x400')`
Button(master, text="Clear",command=EntryDel).grid(row=7, sticky=W)`
Label(master, text="A:").grid(row=0, sticky=W)
entry=Entry()
entry.grid(row=0, column=1)
entry.bind('<Return>', Return_Entry)
Label(master, text="B:").grid(row=1, sticky=W)
entry=Entry()
entry.grid(row=1, column=1)
entry.bind('<Return>', Return_EntryB)`
Label(master, text="C:").grid(row=2, sticky=W)
entry=Entry()
entry.grid(row=2, column=1)
entry.bind('<Return>',Return_EntryC)
Label(master, text="Result:").grid( row=3,column=0 )
resultBox=Entry(master)
resultBox.grid(row=3,column=1)
mainloop()
Your code needed a bit of work. You were overwriting entry variable and so only the last box you created was able to be accessed. This had nothing to do with you removing master as you mentioned in the comments section. What you needed to do is give a unique name to each field. Then for each function you need to change the content to reflect the correct fields.
Here is your code reworked and also changed some function/variable names and spacing to reflect PEP8 standards.
import tkinter as tk
acronym_dictionary = {"A": "Annual", "AC": "Air Conditioning"}
acronym_dictionary_b = {"BA": "British Airway", "BB": "BumbleBee"}
acronym_dictionary_c = {"Ca": "Calcium", "Co": "Company"}
def return_entry(event):
content = entry.get()
result = acronym_dictionary.get(content, "Not found")
print(result)
result_box.delete(0, "end")
result_box.insert("end", result)
def return_entry_b(event):
content = entry2.get()
result = acronym_dictionary_b.get(content, "Not found")
print(result)
result_box.delete(0, "end")
result_box.insert("end", result)
def return_entry_c(event):
content = entry3.get()
result = acronym_dictionary_c.get(content, "Not found")
print(result)
result_box.delete(0, "end")
result_box.insert("end", result)
def entry_del():
result_box.delete(0, "end")
entry.delete(0, "end")
entry2.delete(0, "end")
entry3.delete(0, "end")
master = tk.Tk()
master.title("The Acronym Search Engine")
master.geometry('200x110')
tk.Button(master, text="Clear", command=entry_del).grid(row=7, sticky="w")
tk.Label(master, text="A:", anchor="e").grid(row=0, sticky="ew")
tk.Label(master, text="B:", anchor="e").grid(row=1, sticky="ew")
tk.Label(master, text="C:", anchor="e").grid(row=2, sticky="ew")
tk.Label(master, text="Result:").grid(row=3, column=0)
entry = tk.Entry(master)
entry2 = tk.Entry(master)
entry3 = tk.Entry(master)
result_box = tk.Entry(master)
#result_box = tk.Text(master, width=40, height=3)
entry.grid(row=0, column=1, sticky="w")
entry2.grid(row=1, column=1, sticky="w")
entry3.grid(row=2, column=1, sticky="w")
result_box.grid(row=3, column=1, sticky="w")
entry.bind('<Return>', return_entry)
entry2.bind('<Return>', return_entry_b)
entry3.bind('<Return>', return_entry_c)
master.mainloop()
Results:
That said there is actually a better way to do this than creating a separate dictionary/entry fields with their own variable names.
If we use list we can put all the dictionaries into a list and all the entry fields into a list and then get all the results.
We can also use a textbox to display all results in order.
import tkinter as tk
acronym_dictionary_list = [{"A": "Annual", "AC": "Air Conditioning"},
{"BA": "British Airway", "BB": "BumbleBee"},
{"CA": "Calcium", "CO": "Company"}]
entry_list = []
def return_entry(event):
result_box.delete(1.0, "end")
for ndex, ent in enumerate(entry_list):
if ent.get().strip() != "":
sub_dict = acronym_dictionary_list[ndex]
result_box.insert("end", "{}\n".format(sub_dict.get(ent.get().strip().upper(), "Not found")))
def entry_del():
result_box.delete(1.0, "end")
master = tk.Tk()
master.title("The Acronym Search Engine")
master.geometry('400x200')
for i in range(3):
tk.Label(master, text="{}:".format(chr(ord('#')+i+1)), anchor="e").grid(row=i, column=0, sticky="ew")
entry_list.append(tk.Entry(master))
entry_list[i].grid(row=i, column=1, sticky="w")
entry_list[i].bind('<Return>', return_entry)
result_box = tk.Text(master, width=40, height=3)
tk.Label(master, text="Result:").grid(row=3, column=0)
result_box.grid(row=3, column=1, sticky="w")
tk.Button(master, text="Clear", command=entry_del).grid(row=7, sticky="w")
master.mainloop()
Results:
Sounds like it's because you're overwriting entry on each new "Entry"
entry=Entry(master)
Creates a new entry each time. This probably causes the behavior you're seeing where
each time I add a new dictionary I lose the function of the previous
So I've been struggling with an issue for a week or so, been googling around trying to find different solutions, etc and getting nowhere. I was advised to put functioning code on here so I've cut it down some while still showing the issue.
I want to have a main page listing a set of goals, then if you click on the "Goal Entry" button up top a new window opens where you can input additional goals. Then you type in your desired additions, hit enter, and it adds it to the list on the main page.
I've accomplished all of the above EXCEPT, after you add the goals (and I have the list printing before and after so I know they're being added) and the entry window closes, the list of labels (created by an iteration) hasn't updated accordingly.
How do I get the list on the main page to automatically update when a new item is added to the list?
from tkinter import *
pg = ["goal1","goal2"]
pgtotal=1
psum=len(pg)
class yeargoals():
global pg, hg, fg, rg, rgtotal
def __init__(self,master):
self.master = master
master.title("This Year's Goals")
self.buttonframe = Frame(root)
self.buttonframe.pack(side=TOP, padx = 150, fill=BOTH)
self.home = Button(self.buttonframe, text="Home Page")
self.home.grid(row=1, column=1, padx=10)
self.enter = Button(self.buttonframe, text="Goal Entry", command=self.winenter)
self.enter.grid(row=1, column=2, padx=10)
self.finalize = Button(self.buttonframe, text="Finalize for Year")
self.finalize.grid(row=1, column=3, padx=10)
self.dashboard = Button(self.buttonframe, text="Goal Dashboard")
self.dashboard.grid(row=1,column=4, padx=10)
self.goalframe = Frame(root)
self.goalframe.pack(side=TOP, padx=150, pady=50, fill=BOTH, expand = True)
#Makes the label Fram I want the Checkboxes to go in
self.LabelFramep= LabelFrame(self.goalframe,text="Professional Goals")
self.LabelFramep.pack(side=LEFT, padx=10, anchor = N, fill=BOTH, expand = True)
#Makes the from the list above
for goal in pg:
l = Checkbutton(self.LabelFramep, text=goal, variable=Variable())
l.config(font=("Courier",12))
l.grid(sticky=W)
self.ptotal=Label(self.LabelFramep,text="Progress so far: "+str(pgtotal)+"/"+str(psum))
self.ptotal.config(font=("Courier",12))
self.ptotal.grid(sticky=W)
self.pper=Label(self.LabelFramep, text=str(round((pgtotal/psum)*100))+"% Complete")
self.pper.config(font=("Courier",12))
self.pper.grid(sticky=W)
def winenter(self):
global pg
self.winenter = Toplevel(root)
options = ["Professional", "Health", "Financial", "Reward Items"]
variable = StringVar(self.winenter)
variable.set(options[0])
#Title of entry section
t1 = Label(self.winenter, text="New Goal Entry")
t1.grid(row=0, column=1, columnspan=2)
#dropdown menu
d = OptionMenu(self.winenter, variable, *options)
d.grid(row=1, column=2)
#entry fields
e1 = Entry(self.winenter)
e1.grid(row=2, column=2, padx = 10, pady=5)
e2 = Entry(self.winenter)
e2.grid(row=3, column=2, padx=10, pady=5)
e3 = Entry(self.winenter)
e3.grid(row=4, column=2, padx=10, pady=5)
e4 = Entry(self.winenter)
e4.grid(row=5, column=2, padx=10, pady=5)
e5 = Entry(self.winenter)
e5.grid(row=6, column=2, padx=10, pady=5)
#Label for entry fields
l1 = Label(self.winenter, text="Goal Number 1")
l1.grid(row=2, column=1)
l2 = Label(self.winenter, text="Goal Number 2")
l2.grid(row=3, column=1)
l3 = Label(self.winenter, text="Goal Number 3")
l3.grid(row=4, column=1)
l4 = Label(self.winenter, text="Goal Number 4")
l4.grid(row=5, column=1)
l5 = Label(self.winenter, text="Goal Number 5")
l5.grid(row=6, column=1)
def enter():
global pg, main
print (pg)
if variable.get() == "Professional":
pg.append(e1.get())
self.winenter.destroy()
print (pg)
#Goal entry execute button
b = Button(self.winenter, text="Enter Goals", command=enter)
b.grid(row=7, column = 1)
root = Tk()
Window = yeargoals(root)
root.mainloop()
In your callback function to button "Enter Goals", you have done nothing to update your main window. Maybe you think the main window will magically keep updated with the variable pg, no, you need to do all those updates manually in your callback function.
For example, change your callback enter() to:
def enter():
global pg, main
print (pg)
if variable.get() == "Professional":
pg.append(e1.get())
l = Checkbutton(self.LabelFramep, text=pg[-1], variable=Variable())
l.config(font=("Courier",12))
l.grid(sticky=W)
self.winenter.destroy()
print (pg)
You can find the main window is updated after you click "Enter Goals".