I created a code with a yes/no question, and if yes, I use an entry box to ask how many. But when I reach to that How many question, the label is not showing and I don't understand why?
Thanks in advance, below is the code:
from tkinter import filedialog, messagebox, ttk, constants
from tkinter import *
root = Tk()
root.focus_force()
root.withdraw()
root.call('wm', 'attributes', '.', '-topmost', True)
yesnob = messagebox.askyesno('Test','Do you have a clue?')
if yesnob == True:
root2 = Tk()
root2.call('wm', 'attributes', '.', '-topmost', True)
root2.wm_title('How many ?')
nb_b = 0
title_loop = Label(root2, textvariable = 'How many ?', height = 2, width = 15)
title_loop.grid(row = 1, column = 0)
entrybox = Entry(root2, textvariable = nb_b, width = 5)
entrybox.grid(row = 2, column = 0)
def get_data():
global nb_b
try:
nb_b = int((entrybox.get()))
except ValueError:
no_int = messagebox.showerror('Error', 'You did not enter a number, try again!')
root.destroy()
root2.destroy()
exit_but = Button(root2, text = 'OK', command = get_data, height = 3, width = 5)
exit_but.grid(row = 3, column = 1)
root2.mainloop()
else:
root.destroy()
root.mainloop()
Changing the "textvariable" to "text" worked for me:
title_loop = Label(root2, text = 'How many ?', height = 2, width = 15)
You created the Label with the textvariable argument. If you change it to text the label is shown:
title_loop = Label(root2, text= 'How many ?', height = 2, width = 15)
textvariable can be used in combination with a StringVar if you want to have a text that can be changed. If the text is static use the text argument.
Related
Trying to create a python program in tkinter to mark attendance of persons engaged in a special duty. By clicking the button containing their name the figure right to their name is incremented by 1. While i created the function when any button is placed all figures are got incremented. And the attempt finally reached here.
from tkinter import *
staff=['GEORGE ', 'JAMES ', 'THOMAS', 'MATHEW',
'CLETUSCRUZ', 'FREDY', 'PAUL', 'MEGANI', 'BILL',
'JULIA ']
def factory(number):
def f():
number.set(number.get()+1)
return f
functions =[]
for i in range(10):
functions.append(factory(i))
for i in functions:
f()
window = Tk()
window.title(" Duty List")
window.geometry('320x900')
number = IntVar()
row_value =3
for i in staff:
ibutton = Button(window, text= i, command=clicked)
ibutton.grid(column=1, row=row_value)
ilabel = Label(window, textvariable=number)
ilabel.grid(column=2,row=row_value)
row_value+=1
window.mainloop()`
Factory now creates a unique IntVar for each individual.
link connects button press to onclick for processing IntVar
I've used columnconfigure to push the numbers to the right hand side of window
import tkinter as tk
staff=["GEORGE ", "JAMES ", "THOMAS", "MATHEW",
"CLETUSCRUZ", "FREDY", "PAUL", "MEGANI", "BILL",
"JULIA "]
window = tk.Tk()
window.title(" Duty List")
window.columnconfigure(1, weight = 1)
def factory(n):
return tk.IntVar(value = n)
def onclick(a):
b = a.get()+1
a.set(b)
def link(a, b):
return lambda: a(b)
for i,n in enumerate(staff):
b = factory(0)
a = tk.Button(window, text= n, bd = 1)
a.grid(column = 0, row = i, sticky = tk.NW, padx = 4, pady = 4)
a["command"] = link(onclick, b)
l = tk.Label(window, text = "", textvariable = b, anchor = tk.NW)
l.grid(column = 1, row = i, sticky = tk.NE, padx = 4, pady = 4)
window.geometry("200x319")
window.resizable(False, False)
window.mainloop()
I'm attaching the code below.
There is an event on "focus out", the event triggers once when the code is initialized. Afterwards focusing out of the Spinbox does not trigger the event anymore. The question is, why? And, how do I fix that?
code :
import tkinter as tk
import os, time
def spinBoxValidateRange(widget_name):
print(str(widget_name.winfo_name()) + " focus out")
# Making a window, and giving it some settings
root = tk.Tk()
root.resizable(False, False)
root.winfo_toplevel().title("Test")
# creating a user GUI
default_pady = 2
default_padx = 5
sbx_max_img_width = tk.Spinbox(from_=500, to=5000, width = 4)
sbx_max_img_width.delete(0, 'end')
sbx_max_img_width.insert(0, 1000)
sbx_max_img_height = tk.Spinbox(from_=500, to=5000, width = 4)
sbx_max_img_height.delete(0, 'end')
sbx_max_img_height.insert(0, 1000)
sbx_max_img_width.grid(row = 0, column = 1, sticky = "W", pady = default_pady, padx = default_padx)
sbx_max_img_height.grid(row = 0, column = 3, sticky = "W", pady = default_pady, padx = default_padx)
sbx_max_img_width.bind("<FocusOut>", spinBoxValidateRange(sbx_max_img_width))
sbx_max_img_height.bind("<FocusOut>", spinBoxValidateRange(sbx_max_img_height))
root.mainloop()
Here is the corrected code (that works) -
import tkinter as tk
import os, time
def spinBoxValidateRange(some_widget):
print(str(some_widget.widget.winfo_name()) + " focus out")
# Making a window, and giving it some settings
root = tk.Tk()
root.resizable(False, False)
root.winfo_toplevel().title("Test")
# creating a user GUI
default_pady = 2
default_padx = 5
sbx_max_img_width = tk.Spinbox(from_=500, to=5000, width = 4)
sbx_max_img_width.delete(0, 'end')
sbx_max_img_width.insert(0, 1000)
sbx_max_img_height = tk.Spinbox(from_=500, to=5000, width = 4)
sbx_max_img_height.delete(0, 'end')
sbx_max_img_height.insert(0, 1000)
sbx_max_img_width.grid(row = 0, column = 1, sticky = "W", pady = default_pady, padx = default_padx)
sbx_max_img_height.grid(row = 0, column = 3, sticky = "W", pady = default_pady, padx = default_padx)
sbx_max_img_width.bind("<FocusOut>", lambda parameter = sbx_max_img_width: spinBoxValidateRange(parameter))
sbx_max_img_height.bind("<FocusOut>", lambda parameter = sbx_max_img_height: spinBoxValidateRange(parameter))
root.mainloop()
I would like print all the information present in the excel data in new tkinter window
You can use Tkinter's grid.
For example, to create a simple excel-like table:
from Tkinter import *
root = Tk()
height = 5
width = 5
for i in range(height): #Rows
for j in range(width): #Columns
b = Entry(root, text="")
b.grid(row=i, column=j)
mainloop()
To print, consider the following example in which I make a button with Tkinter that gets some text from a widget and then prints it to console using the print() function.
from tkinter import *
from tkinter import ttk
def print_text(*args):
try:
print(text1.get())
except ValueError:
pass
root = Tk()
root.title("Little tkinter app for printing")
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column = 0, row = 0, sticky = (N,W,E,S))
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
text1 = StringVar()
text_entry = ttk.Entry(mainframe, width = 20, textvariable=text1)
text_entry.grid(column = 1, row = 2, sticky = (N,W,E,S))
ttk.Button(mainframe, text = "Print!", command =
print_text(text1)).grid(column = 1, row = 3, sticky = (E))
for child in mainframe.winfo_children():
child.grid_configure(padx = 5, pady = 5)
text_entry.focus()
root.bind('<Return>', print_text)
root.mainloop()
I am being particularly obtuse. I am iterating through a list of technical italian words and wanting to insert a translation using a tkinter interface. There is no problem doing this without the GUI: My problem is that I cannot figure out how to do an iteration, load a word into a ttk.Label and wait for a user entry in a ttk.Entry field. I have searched and found explanations, but I am at a loss how to apply the suggestions. This is my code using a trivial list of words:
from tkinter import ttk
import tkinter as tk
def formd():
list_of_terms = ['aardvark', 'ant','zombie', 'cat', 'dog', 'buffalo','eagle', 'owl','caterpiller', 'zebra', 'orchid','arum lily' ]
discard_list = []
temp_dict={}
list_of_terms.sort()
for item in list_of_terms:
listKey.set(item)
# need to wait and get user input
translation =dictValue.get()
temp_dict[item]=translation
discard_list.append(item)
# check if it has worked
for key, value in temp_dict.items():
print(key, value)
# GUI for dict from list
LARGE_FONT= ("Comic sans MS", 12)
root = tk.Tk()
root.title('Nautical Term Bilingual Dictionary')
ttk.Style().configure("mybtn.TButton", font = ('Comic sans MS','12'), padding = 1, foreground = 'DodgerBlue4')
ttk.Style().configure('red.TButton', foreground='red', padding=6, font=('Comic sans MS',' 10'))
ttk.Style().configure('action.TLabelframe', foreground = 'dodger blue3')
#.......contents frames.....................
nb = ttk.Notebook(root)
page5 = ttk.Frame(nb)
# declare variables
listKey= tk.StringVar()
dictValue = tk.StringVar()
# widgets
keyLabel =ttk.Label( page5, text = "key from list", font=LARGE_FONT).grid(row=3, column = 0)
Keyfromlist =ttk.Label(page5, width = 10, textvariable = listKey).grid(row = 3, column = 1)
valueLabel =ttk.Label( page5, text = "enter translation", font=LARGE_FONT).grid(row=3, column = 2)
listValue =ttk.Entry(page5, textvariable =dictValue, width = 15).grid(row = 3, column = 3)
#listValue.delete(0,'end')
#listValue.focus_set()
# add buttons
b1 = ttk.Button(page5, text="add to dictionary",style = "mybtn.TButton", command = formd)
b1.grid(row = 5, column = 0)
b5 = ttk.Button(page5, text="clear entry", style ="mybtn.TButton")
b5.grid(row = 5, column = 2)
nb.add(page5, text='From List')
nb.pack(expand=1, fill="both")
for child in root.winfo_children():
child.grid_configure(padx =5, pady=5)
if __name__ == "__main__":
root.mainloop()
I wonder whether someone could take the time to suggest a solution, please. How to stop a while loop to get input from user using Tkinter? was the one suggestion that I cannot figure how to use in my example
tkinter doesn't "play nice" with while loops.
Fortunately for you, you don't need to use one.
You can do something like the below:
from tkinter import *
class App:
def __init__(self, root):
self.root = root
self.list = ['aardvark', 'ant','zombie', 'cat', 'dog', 'buffalo','eagle', 'owl','caterpiller', 'zebra', 'orchid','arum lily' ]
self.text = Label(self.root, text="aardvark")
self.entry = Entry(self.root)
self.button = Button(self.root, text="Ok", command=self.command)
self.text.pack()
self.entry.pack()
self.button.pack()
def command(self):
print(self.text.cget("text")+" - "+self.entry.get())
try:
self.text.configure(text = self.list[self.list.index(self.text.cget("text"))+1])
except IndexError:
self.entry.destroy()
self.button.destroy()
self.text.configure(text = "You have completed the test")
root = Tk()
App(root)
root.mainloop()
This essentially uses the Button widget to iterate to the next text and get the next input.
I have this code:
from tkinter import *
from tkinter import ttk
class Application:
def __init__(self, master):#Change to game class when combining code
self.master = master#remove when combining code
self.frame_Canvas = ttk.Frame(self.master, width = 600, height = 600)
self.frame_Canvas.pack(side = 'left')
self.frame_Canvas.pack_propagate(False)
self.frame_Canvas.grid_propagate(False)
self.hangman = Canvas(self.frame_Canvas, width = 600, height = 600,
background = 'white').pack()
self.FullName = ttk.Label(self.frame_Canvas, text = "Full Name", background = 'white')#full name will be entered here
self.FullName.config(font=("TkDefaultFont", 20))
self.FullName.place(x = 10, y = 10)
self.frame_Interact = ttk.Frame(self.master, width = 200, height = 600)
self.frame_Interact.pack(side = 'right')
self.frame_Interact.pack_propagate(False)
self.frame_Interact.grid_propagate(False)
self.QuestionLabel = ttk.Label(self.frame_Interact, text = "Question:")
self.QuestionLabel.config(font=("TkDefaultFont", 20))
self.QuestionLabel.grid(column = 0, row = 0)
self.QuestionShow = Text(self.frame_Interact, height=1, width=8)#input question here
self.QuestionShow.config(font=("TkDefaultFont", 20))
self.QuestionShow.grid(column = 0, row = 1)#FIX THE FORMATTING OF QUESTION, GRID CELL TO LEFT, NOT BIG ENOUGTH?
self.AnswerEntry = ttk.Entry(self.frame_Interact, width = 10)#do later
def main():
root = Tk()
root.wm_title("Hangman")
Menu = Application(root)
root.resizable(width=False, height=False)
root.iconbitmap("windowicon.ico")
root.mainloop()
if __name__ == "__main__": main()
I dont know why, but the Answer box and label on the right side of my tkinter GUI is on the left side of its frame. I want it in the center. Does anyone know a way to frix it, or any improvements for the code so far. Thanks :)
There are two ways you can do this, first way will to be to use .pack() instead of .grid() since pack is very easy to use and does the aligning for you automatically.
So you can just replace:
self.QuestionLabel.grid(column = 0, row = 0)
# and
self.QuestionShow.grid(column = 0, row = 1)
With:
self.QuestionLabel.pack()
# and
self.QuestionLShow.pack()
This way isn't recommended for your situation whatsoever, since that will involve mixing pack and grid together which could cause future errors in your code.
As Bryan Oakley said:
it will cause errors immediately, if the widgets share the same parent. It won't ever cause problems if the widgets have different parents.
You should instead do this:
from tkinter import *
from tkinter import ttk
class Application:
def __init__(self, master):#Change to game class when combining code
self.master = master#remove when combining code
self.frame_Canvas = ttk.Frame(self.master, width = 600, height = 600)
self.frame_Canvas.pack(side = 'left')
self.frame_Canvas.pack_propagate(False)
self.frame_Canvas.grid_propagate(False)
self.hangman = Canvas(self.frame_Canvas, width = 600, height = 600,
background = 'white').pack()
self.FullName = ttk.Label(self.frame_Canvas, text = "Full Name", background = 'white')#full name will be entered here
self.FullName.config(font=("TkDefaultFont", 20))
self.FullName.place(x = 10, y = 10)
self.frame_Interact = ttk.Frame(self.master, width = 200, height = 600)
self.frame_Interact.pack(side = 'right')
self.frame_Interact.pack_propagate(False)
self.frame_Interact.grid_propagate(False)
Grid.columnconfigure(self.frame_Interact, 0, weight=1) # NOTE, THIS CHANGED
self.QuestionLabel = ttk.Label(self.frame_Interact, text = "Question:")
self.QuestionLabel.config(font=("TkDefaultFont", 20))
self.QuestionLabel.grid(column = 0, row = 0)
self.QuestionShow = Text(self.frame_Interact, height=1, width=8)
self.QuestionShow.config(font=("TkDefaultFont", 20))
self.QuestionShow.grid(column = 0, row = 1)
def main():
root = Tk()
root.wm_title("Hangman")
Menu = Application(root)
root.resizable(width=False, height=False)
root.iconbitmap("windowicon.ico")
root.mainloop()
if __name__ == "__main__":
main()
By adding Grid.columnconfigure(self.frame_Interact, 0, weight=1) it will help grid know how to allocate extra space. so that the label will try to take up the whole column. The same goes for rows if you're wondering, you can add Grid.rowconfigure(self.frame_Interact, 0, weight=1) to make the widgets fill the whole row.
And for some improvements to your code, you should change this line:
self.hangman = Canvas(self.frame_Canvas, width = 600, height = 600,
background = 'white').pack()
# to
self.hangman = Canvas(self.frame_Canvas, width = 600, height = 600, background = 'white')
self.hangman.pack()
Or else self.hangman will be None, as it is in your code.