This question already has answers here:
tkinter creating buttons in for loop passing command arguments
(3 answers)
Closed 2 years ago.
Hello im trying to create a questionnaire with 5 choises for each question. Since I have lots of questions, I wanted to create labels and radiobuttons in a loop. However, I can not call mainloop() function of tkinter in a loop so when I call it on the outside of the loop, my selection on the questionnaire of any question becomes the answer of the last question. How can I fix this?
def selected(value, question):
answer_values[question-1] = value
print(value, question)
root = Tk()
root.title('Kişilik Analiz Testi')
answers = {}
for x in range(0, enneagram.shape[0]):
soru = str(x+1) + ". " + enneagram.SORULAR[x] + " Cümlesi sizi ne kadar iyi ifade ediyor?"
myLabel = Label(root, text = soru).grid(row = x+1, column = 1, sticky = W)
Label(root, text = "Sorular").grid(row = 0, column = 1, sticky = W)
Label(root, text = "Çok Zayıf ").grid(row = 0, column = 2)
Label(root, text = "Zayıf ").grid(row = 0, column = 3)
Label(root, text = "Orta ").grid(row = 0, column = 4)
Label(root, text = " İyi ").grid(row = 0, column = 5)
Label(root, text = "Çok İyi").grid(row = 0, column = 6)
answers["soru{0}".format(x)] = IntVar()
answers["soru{0}".format(x)].set(3)
button = Radiobutton(root, variable = answers["soru{0}".format(x)], value = 1, command = lambda: selected(1, x+1)).grid(row = x+1, column = 2)
button = Radiobutton(root, variable = answers["soru{0}".format(x)], value = 2, command = lambda: selected(2, x+1)).grid(row = x+1, column = 3)
button = Radiobutton(root, variable = answers["soru{0}".format(x)], value = 3, command = lambda: selected(3, x+1)).grid(row = x+1, column = 4)
button = Radiobutton(root, variable = answers["soru{0}".format(x)], value = 4, command = lambda: selected(4, x+1)).grid(row = x+1, column = 5)
button = Radiobutton(root, variable = answers["soru{0}".format(x)], value = 5, command = lambda: selected(5, x+1)).grid(row = x+1, column = 6)
root.mainloop()
When I run this cell, i get this window. Default choice is the middle one. When I click on other choices it prints out the index of the last question:
Try this code:
import tkinter as tk
from functools import partial
def function(i):
print("You toggled number %i"%i)
print([var.get() for var in variables])
root = tk.Tk()
variables = []
for i in range(5):
# Create the new variable
variable = tk.IntVar()
variables.append(variable)
# Create the command using partial
command = partial(function, i)
# Create the radio button
button = tk.Radiobutton(root, variable=variable, value=i, command=command)
button.pack()
root.mainloop()
It uses the partial function/class from functools.
Related
I am a newbie in python. I am trying to write a program to reference books, book chapters and journal articles in Harvard and APA style. I need to be able to print the entry from the user.
The code displays three windows. In the first, the user is asked to choose the referencing style (Harvard/APA) and when clicking the button it opens a second window which allows the user to choose the source (book/book chapter/journal). Then a third window opens which allows the user to input the information that is required (author/year/title and so on).
After this, the user must click another button done to see the full reference. To visualise the execution, select Harvard, then Book, as I have only written that part of the code.
from tkinter import *
def book_harvard():
reference = author_entry.get()
reference_1 = year_entry.get()
reference_2 = title_entry.get()
string_to_display = reference + reference_1 + reference_2
print(string_to_display)
def TypeofTextHarvard():
second = Toplevel(first)
first.withdraw()
second.title("Type of Source")
Source = Label (second, text = "What type of source would you like to reference?").grid(column = 1, row = 0)
Book = Button (second, text = "Book", command = Harvard).grid(column = 1, row = 1)
Chapter = Button (second, text = "Book Chapter").grid (column = 1, row = 2)
Journal = Button (second, text = "Journal Article").grid (column = 1, row = 3)
first = Tk()
first.title("Referencing Style")
Reference = Label (first, text = "Which referencing style would you like to use?").grid(column = 1, row = 0)
Harvard = Button (first, text = "Harvard Style", command = TypeofTextHarvard).grid (column = 1, row = 1)
APA = Button (first, text = "APA Style").grid (column = 1, row = 2)
def Harvard():
third = Toplevel()
third.title("book")
author = StringVar()
year = StringVar()
title = StringVar()
author_label = Label(third, text = "Author")
author_entry = Entry(third)
year_label = Label(third, text = "Year")
year_entry = Entry(third)
title_label = Label(third, text = "Title")
title_entry = Entry(third)
button_1 = Button(third, text = "Done", command = book_harvard)
author_label_2 = Label(third, textvariable = author)
year_label_2 = Label(third, textvariable = year)
title_label_2 = Label(third, textvariable = title)
author_label.grid (row = 0, column = 0)
author_entry.grid (row = 0, column = 1)
year_label.grid (row = 1, column = 0)
year_entry.grid (row = 1, column = 1)
title_label.grid (row = 2, column = 0)
title_entry.grid (row = 2, column = 1)
button_1.grid (row = 3, column = 0)
author_label_2.grid (row = 4, column = 1)
year_label_2.grid (row = 4, column = 2)
title_label_2.grid (row = 4, column = 3)
first.mainloop()
However I get the following error:
reference = author_entry.get()
NameError: name 'author_entry' is not defined
The cause of the NameError is because author_entry is a variable local to the Harvard() function, so can't be referenced outside of it, such as in the separate book_harvard() function. The simplest—although not the best—solution is to make it a global variable. The other Entry widgets potentially have the same problem, so in the code below I have declared all of them global.
I also noticed another potential issue you're likely to run into, namely assigning the return value of the grid() method to a variable. e.g.:
Book = Button(second, text="Book", command=Harvard).grid(column=1, row=1)
This is not doing what you think because the grid() method always returns None, so that's the value that's getting assigned to Book. I haven't fixed these, but doing so is easy, just create the widget first and assign it to a variable, and then on another line, all variable.grid(...).
One final piece of advice: read and start following the PEP 8 - Style Guide for Python Code. I've done that to some degree to the version of your code with the fix in it shown below.
FYI: The accepted answer to the question Best way to structure a tkinter application describes an excellent object-oriented way to structure and implement Tkinter-based applications.
from tkinter import *
def book_harvard():
global author_entry, year_entry, title_entry # ADDED
reference = author_entry.get()
reference_1 = year_entry.get()
reference_2 = title_entry.get()
string_to_display = reference + reference_1 + reference_2
print(string_to_display)
def TypeofTextHarvard():
second = Toplevel(first)
first.withdraw()
second.title("Type of Source")
Source = Label(second, text = "What type of source would you like to reference?").grid(column=1, row=0)
Book = Button(second, text="Book", command=Harvard).grid(column=1, row=1)
Chapter = Button(second, text="Book Chapter").grid(column=1, row=2)
Journal = Button(second, text="Journal Article").grid(column=1, row=3)
first = Tk()
first.title("Referencing Style")
Reference = Label(first, text="Which referencing style would you like to use?").grid(column=1, row=0)
Harvard = Button(first, text="Harvard Style", command=TypeofTextHarvard).grid(column=1, row=1)
APA = Button(first, text="APA Style").grid(column=1, row=2)
def Harvard():
global author_entry, year_entry, title_entry # ADDED
third = Toplevel()
third.title("book")
author = StringVar()
year = StringVar()
title = StringVar()
author_label = Label(third, text="Author")
author_entry = Entry(third)
year_label = Label(third, text="Year")
year_entry = Entry(third)
title_label = Label(third, text="Title")
title_entry = Entry(third)
button_1 = Button(third, text="Done", command=book_harvard)
author_label_2 = Label(third, textvariable=author)
year_label_2 = Label(third, textvariable=year)
title_label_2 = Label(third, textvariable=title)
author_label.grid(row=0, column=0)
author_entry.grid(row=0, column=1)
year_label.grid(row=1, column=0)
year_entry.grid(row=1, column=1)
title_label.grid(row=2, column=0)
title_entry.grid(row=2, column=1)
button_1.grid(row=3, column=0)
author_label_2.grid(row=4, column=1)
year_label_2.grid(row=4, column=2)
title_label_2.grid(row=4, column=3)
first.mainloop()
I've created a temperature converter programme in which the calculated temperature from an entry widget gets displayed in a separate label, what I need to do is to grab that converted variable and put it into a list.
I think that making a connected entry widget to the label widget would work where they are connected so I could grab the variable using the .get method but that would look awfully messy. Is there any other way I could proceed with this?
This is my first post and I am a beginner in Python, very sorry if the code looks messy and if I included too much code.
data = []
tempVal = "Celcius"
def store_temp(sel_temp):
global tempVal
tempVal = sel_temp
class Calculator:
def __init__(self, num_a, num_b):
self.num_a= num_a
self.num_b = num_b
def convert(self):
if tempVal == 'Fahrenheit':
return float((float(self.num_a) - 32)* 5 / 9)
if tempVal == 'Celcius':
return float((float(self.num_a) * 9/ 5) + 32)
def display_add(entry_numa,entry_numb,label_answer):
#get the value from entry_numa
num_a = entry_numa.get()
num_b = entry_numb.get()
num_a = str(num_a)
num_b = str(num_b)
#create an object
global data
calc = Calculator(num_a,num_b)
label_answer['text'] = calc.convert()
data += [calc]
def calc_history():
global data
#creat e another window
window_calc_list = Tk()
window_calc_list.geometry("400x200")
#create a listbox
listbox_calc_list = Listbox(window_calc_list, width= 300)
listbox_calc_list.pack()
listbox_calc_list.insert(END, "list of data")
for info in data:
listbox_calc_list.insert(END, str(info.num_a) + " " + str(info.num_b) + " " )
window_calc_list.mainloop()
def main():
window = Tk()
window.geometry("500x150")
validate_letter = window.register(only_letters)
validate_nb = window.register(only_numbers_max_3)
label = Label(window, width = 30, background = 'lightblue', text='enter temperature, only numbers')
label.grid(row=0, column=0)
entry_numa = Entry(window, width = 30, validate="key", validatecommand=(validate_nb, '%d', '%P'))
entry_numa.grid(row = 0, column = 1)
#create another label and entry object for num_b
label_numb = Label(window, width = 30, background = 'lightblue', text='enter location, only letters')
label_numb.grid(row=1, column=0)
entry_numb = Entry(window, width = 30, validate="key", validatecommand=(validate_letter, '%d', '%S'))
entry_numb.grid(row = 1, column = 1)
#create another label to display answer
label_answer = Label(window, width = 30, background = 'lightyellow')
label_answer.grid(row = 2, column = 1)
entry_answer = Entry(window, width = 30)
entry_answer.grid(row = 2, column = 0)
button_add = Button(window, text = "ADD", command = lambda: display_add(entry_numa,entry_numb,label_answer))
button_add.grid(row=3, column = 0)
button_delete = Button(window, text = "DELETE", command = lambda: delete_data(data))
button_delete.grid(row=3, column = 2)
#create another button to display all previous calculations
button_display = Button(window,text = "calc_history", command = lambda: calc_history())
button_display.grid(row=3, column = 1)
var = StringVar()
dropDownList = ["Celcius", "Fahrenheit"]
dropdown = OptionMenu(window, var,dropDownList[0], *dropDownList, command=store_temp)
dropdown.grid(row=0, column=2)
window.mainloop()
A tk.Label displayed value can be accessed via the text property
, labelwidgetname['text'].
Depeneding on when and how you want the independent list of stored values
to be updated there are a variety of options. The example shows one if the
user is required to press a submission button. This could be adapted,
for example,when the tempreture calculation is performed.
Of course it would be simpler to update the list of stored values directly at the point in the script where the calculated tempreture for the label text has been derived.
import tkinter as tk
stored_values = []
def add_labelvalue_tolist(temp):
'''Store label value to list.'''
stored_values.append(temp)
print('contents of list', stored_values)
def add_entry_tolabel(event):
display_label['text'] = user_entry.get()
ROOT = tk.Tk()
user_entry = tk.Entry()
user_entry.grid(column=0, row=0)
user_entry.bind('<KeyRelease>', add_entry_tolabel)
display_label = tk.Label()
display_label.grid(column=1, row=0)
# update list via button command linked to label text value
add_button = \
tk.Button(text='add to list',
command=lambda:add_labelvalue_tolist(display_label['text']))
add_button.grid(column=0, row=1)
ROOT.mainloop()
try making a function that is like this
def letterused():
converter=(letter.get())# letter is a entry box at the bottom is the code
converted.set(converter)
for i in range(1):
used_letters1.append(converter) #list
letter = ttk.Entry(root, width = 20,textvariable = letter)
letter.pack()
I would like user to click on the number's and then the number should change color and i shall be able to capture on what label user has clicked, this form then shall be saved in Text and PDF format..Thanks a mil in advance for any help
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
class Proj_pres:
"""Defininf clickable labels in frame"""
#def fr_lb(self):
def __init__(self,master):
master.title(" Feedback Form")
#master.resizable(False,False)
self.frame_header = ttk.Frame(master, borderwidth = 5, relief ='ridge').grid(sticky = NE)
#self.frame_header.pack()
ttk.Label(self.frame_header, text = " For recording feedback on Autumn(inerm) project presentations",
font=('Arial',16,'bold')).grid(row = 0, column = 0,sticky = NW)
"""Defining new frame"""
self.frame_content = ttk.Frame(master,borderwidth = 5)
self.frame_content.grid(row = 2, column = 0,columnspan = 3, sticky = NW)
"""Adding check buttons for Studio 1 and Studio 2"""
self.chkb1 = IntVar()
self.b1 = ttk.Checkbutton(self.frame_content, text = "UC1Studio1", variable = self.chkb1).grid(row =0,column = 0)
self.chkb2 = IntVar()
self.b2 = ttk.Checkbutton(self.frame_content, text = "UC2Studio2", variable = self.chkb2).grid(row = 0, column = 8,columnspan = 2,stick=W)
"""Adding Labels for Team and Reviewer"""
ttk. Label(self.frame_content, text = "Team Name").grid(row =4, column = 0,sticky = W)
ttk.Label(self.frame_content, text = "Reviewer").grid(row = 4,column = 7, sticky = E)
ttk.Label(self.frame_content).grid(row=2, column=0)
"""Adding Entry Boxes for team name and reviewer"""
ttk.Entry(self.frame_content).grid( row = 4, column = 1,columnspan = 4,sticky = W)
ttk.Entry(self.frame_content).grid( row = 4, column = 8,columnspan = 2, sticky = E)
"""Adding Label and frame for grading info"""
self.frame_info = ttk.Frame(master,borderwidth = 5, relief = 'solid')
self.frame_info.grid(row = 3, column = 0,sticky = NW)
ttk.Label(self.frame_info).grid(row =5,column = 0)
ttk.Label(self.frame_info, text ="Please use the feeedback scale for each of the following criterion, "
"where 5 = excellent and 1 = poor").grid(row = 7, column = 0,sticky = W)
ttk.Label(self.frame_info).grid(row = 6, column =0)
ttk.Label(self.frame_info,text = "OVERVIEW OF PROJECT").grid(row = 8, column = 0, sticky = NW)
ttk.Label(self.frame_info, text = " 5: Well Structured,4: Clear aim, 3:Understandable project "
"view").grid(row = 9, column = 0, sticky = NW)
ttk.Label(self.frame_info, text=" 2: Absent,1: Confused "
"view").grid(row=9, column=5, sticky=NW)
#ttk.Label(self.frame_info, text=" should come here").grid(row=9, column=1, sticky=NW)
"""Adding frame in column 2 for clickable Labels"""
self.frame_clk=ttk.Frame(self.frame_info, borderwidth= 5, relief ='solid')
self.frame_clk.grid(row = 9,column = 2,columnspan = 3,sticky = NW)
self.f1_l5 = StringVar()
l5 = ttk.Label(self.frame_clk,text = " 5 " ,
background = 'white',borderwidth=5,relief= 'ridge',font =('Helvetica',12,'bold'))
#,textvariable = self.f1_l5
l5.grid(row=0,column =1,columnspan =2 )
f1_l4= ttk.Label(self.frame_clk, text=" 4 ",background = 'white',borderwidth=5,relief= 'ridge', font=('Helvetica', 12, 'bold'))
f1_l4.grid(row =0 , column = 3)
f1_l3 = ttk.Label(self.frame_clk, text=" 3 ",background = 'white',borderwidth=5,relief= 'ridge', font=('Helvetica', 12, 'bold'))
f1_l3.grid(row=0, column=4)
f1_l2 = ttk.Label(self.frame_clk, text=" 2 ",background = 'white',borderwidth=5,relief= 'ridge', font=('Helvetica', 12, 'bold'))
f1_l2.grid(row=0, column=5)
f1_l1 = ttk.Label(self.frame_clk, text=" 1 ",background = 'white', borderwidth=5,relief= 'ridge',font=('Helvetica', 12, 'bold'))
f1_l1.grid(row=0, column=6)
#elf.frame_content.pack()
def main():
root = Tk()
proj_pres = Proj_pres(root)
root.mainloop()
if __name__ == '__main__':main()
def clickFunction(event): #event is argument with info about event that triggered the function
global selectedNumber #make the number visible throughout the program, don't need this if you'll just pass it as argument to function
event.widget.config(background = "green") #event.widget is reference to widget that was clicked on and triggered the function
selectedNumber = 7 - event.widget.grid_info()["column"] #grid info is dictionary with info about widget's grid relative to widget, more at http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/grid-methods.html
if(selectedNumber > 5): selectedNumber = 5
print(selectedNumber)
''' if someday you won't use grid, but will use list to store Labels, this is a way to get Label's position
selectedNumber = myLabels.index(event.widget)
'''
l5.bind("<Button-1>", clickFunction)
f1_l4.bind("<Button-1>", clickFunction)
f1_l3.bind("<Button-1>", clickFunction)
f1_l2.bind("<Button-1>", clickFunction)
f1_l1.bind("<Button-1>", clickFunction)
''' Alternative way for making lots of similar widgets, not to mention extending Label class
myLabels = [] #create List to make code more compact and to be able to use loops
for i in range(5, 0, -1):
myLabels.append(ttk.Label(self.frame_clk, text=" " + str(i) + " ",background = 'white',borderwidth=5,relief= 'ridge', font=('Helvetica', 12, 'bold'))
myLabels.bind("<Button-1>", clickFunction)
myLabels[i].grid(row =0 , column = 6 - i)
'''
Here is code you can add below "f1_l1.grid(row=0, column=6)" line (around ln 77). But I think you might need RadioButton for that purpose since it automatically unmarks other options and supports IntVar. More about events: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/events.html This webpage has excellent (but a bit outdated) documentation.
Btw, there is one quick fix you might want to apply when making programs for yourself. In Python you can add fields to classes and their instances outside their definition. E.g. in your code, you cold have written f1_l1.myNumber = 1 after "creating" it and in clickFunction instead of grid_info() use selectedNumber = event.widget.myNumber. It'd do the thing, but don't tell them I taught you that ;) since it isn't considered good practice adding fields that way.
If you have any more questions feel free to ask.
Hello Python community,
Im using Python 3.6 and Im stumped on how to display a stored item in an empty list to a list box. Can anyone evaluate my code and tell me what I'm missing? Thanks in advance!
from tkinter import *
root = Tk()
root.title("Name Entry")
root.geometry("240x250")
mylist = []
def get_data(l):
l.append(box1.get())
print(l)
label1 = Label(root,text = "ID:",height = 2)
label1.grid(row = 0, column = 0)
ID=StringVar()
box1 = Entry(root, bd = 4, textvariable = ID)
box1.grid(row = 0, column = 1)
botonA = Button(root, text = "accept",command=lambda: get_data(mylist), width = 5)
botonA.grid(row = 0, column = 2)
list_names = Listbox(root).grid(row = 2, column = 1, rowspan = 7)
for item in mylist:
list_names.insert("end", item)
root.mainloop()
With the help from Matteo, I was able to creat what I wanted. Thanks again for clearing this up for me! :)
{from tkinter import *
root = Tk()
root.title("Name Entry")
root.geometry("240x250")
mylist = []
def get_data(l):
l.append(box1.get())
print(l)
display_data()
def display_data():
list_names.delete(0, "end")
for items in mylist:
list_names.insert(END, items)
label1 = Label(root,text = "ID:",height = 2)
label1.grid(row = 0, column = 0)
ID = StringVar()
box1 = Entry(root, bd = 4, textvariable = ID)
box1.grid(row = 0, column = 1)
botonA = Button(root, text = "accept",command = lambda: get_data(mylist),
width = 5)
botonA.grid(row = 0, column = 2)
list_names = Listbox(root)
list_names.grid(row = 2, column = 1, rowspan = 7)
root.mainloop()}
You have to insert the element when the button is pressed! In your code you are adding it to the listbox when mylist was empty.
Here is the working code:
from tkinter import *
root = Tk()
root.title("Name Entry")
root.geometry("240x250")
mylist = []
def get_data(l):
l.append(box1.get())
list_names.insert(END, l)
print(l)
label1 = Label(root, text="ID:", height=2)
label1.grid(row=0, column=0)
ID = StringVar()
box1 = Entry(root, bd=4, textvariable=ID)
box1.grid(row=0, column=1)
botonA = Button(root, text="accept", command=lambda: get_data(mylist), width=5)
botonA.grid(row=0, column=2)
list_names = Listbox(root)
list_names.grid(row=2, column=1, rowspan=7)
root.mainloop()
I also modified two other things:
I'm not sure if it's what you wanted but l.append(box1.get()) adds to the listbox all the element of the list, and not just the last one as I think you need.
list_names = Listbox(root).grid(row = 2, column = 1, rowspan = 7) means that the list_names variable is the result of the grid function (which is None). You have to first save the ListBox variable, and the grid it.
Trying to make a very basic addition calculator with python and tkinter. It gives me an error:
btresult = Button(window, text = "Compute Sum", command = self.result).grid(row = 4, column = 2, sticky = E)
^
SyntaxError: invalid syntax
I am having trouble figuring out how to connect this.
from tkinter import *
class addCalculator:
def __init__(self):
window = Tk()
window.title("Add Calculator")
Label(window, text = "First Number: ").grid(row = 1, column = 1, sticky = W)
Label(window, text = "Second Number: ").grid(row = 2, column = 1, sticky = W)
self.number1Var = StringVar()
Entry(window, textvariable = self.number1Var, justify = RIGHT).grid(row = 1, column = 2)
self.number2Var = StringVar()
Entry(window, textvariable = self.number2Var, justify = RIGHT).grid(row = 2, column = 2)
self.resultVar = StringVar()
lblresult = Label(window, textvariable = self.result.grid(row = 3, column = 2, sticky = E)
btresult = Button(window, text = "Compute Sum", command = self.result).grid(row = 4, column = 2, sticky = E)
def result(self):
resultVar = self.resultVar.set(eval(self.number1Var.get()) + eval(self.number2Var.get()))
return resultVar
window.mainloop()
addCalculator()
On the previous line (lblresult = ...), you forgot to close your opened parentheses. Python interprets this (both that line and the next line, btresult = ...) as one whole line of code, but obviously this can't work with your code, hence the SyntaxError
I solved this problem in my own way. I tried to stay faithful to the original question but the code needed a lot of clean up. There was lots of little odds and ends to fix, but i think the main problem was the method of passing the integers to the function. I also changed the original lblresult from a label to an Entry widget. Im still new at Python but getting better. I found this question while looking for a similar answer and solving this also solved my problem. Thanks! Code below:
from Tkinter import *
class addCalculator:
def __init__(self):
window = Tk()
window.title("Add Calculator")
def result(z1,z2):
biz=z1+z2
lblresult.delete(0,END)
lblresult.insert(0,biz)
return
Label1 = Label(window, text = "First Number: ").grid(row = 1, column = 1, sticky = W)
Label2 = Label(window, text = "Second Number: ").grid(row = 2, column = 1, sticky = W)
self.number1Var = IntVar()
Entry1 = Entry(window, textvariable = self.number1Var, justify = RIGHT).grid(row = 1, column = 2)
self.number2Var = IntVar()
Entry2 = Entry(window, textvariable = self.number2Var, justify = RIGHT).grid(row = 2, column = 2)
Label3 = Label(window, text = "Result: ").grid(row = 3, column = 1, sticky = W)
lblresult = Entry(window, justify = RIGHT)
lblresult.grid(row = 3, column = 2, sticky = E)
btresult = Button(window,text="Compute Sum",command=lambda:result(self.number1Var.get(),self.number2Var.get()))
btresult.grid(row = 4, column = 2, sticky = E)
window.mainloop()
addCalculator()