Separate fuction for each button - python-3.x

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()

Related

tkinter key binding causes image to disappear

I'm trying to bind arrow keys to buttons or at least the functions of the buttons (button_forward and button_back). The function of the buttons works, however, when I bind a key to the button the image just disappears.
It would also be awesome if someone could help me figure out how to create a loop to define the images and put them into a list. I'm just so lost when it comes to that.
The main purpose of the code is to be an image viewer that flashes an LED strip when an image changes.
I want to be able to control it using arrow keys to move forward and back between the images.
from tkinter import Tk, Button,Label, DISABLED
from PIL import ImageTk,Image
import board
import time
import neopixel
pixels = neopixel.NeoPixel(board.D18, 30)
root= Tk()
root.configure(bg='black')
root.title("please work")
# define, load, show
my_img1 = ImageTk.PhotoImage(Image.open("1.bmp"))
my_img2 = ImageTk.PhotoImage(Image.open("2.bmp"))
my_img3 = ImageTk.PhotoImage(Image.open("3.bmp"))
my_img4 = ImageTk.PhotoImage(Image.open("4.bmp"))
my_img5 = ImageTk.PhotoImage(Image.open("5.bmp"))
my_img6 = ImageTk.PhotoImage(Image.open("6.bmp"))
my_img7 = ImageTk.PhotoImage(Image.open("7.bmp"))
my_img8 = ImageTk.PhotoImage(Image.open("8.bmp"))
image_list = [my_img1, my_img2, my_img3, my_img4, my_img5, my_img6, my_img7, my_img8]
my_label = Label(image=my_img1)
my_label.grid(row = 0, column = 0, columnspan= 3, rowspan = 25, padx=440, pady= 5)
def forward(image_number, event = None):
global my_label
global button_forward
global button_back
my_label.grid_forget()
my_label = Label(image = image_list[image_number-1])
button_forward = Button(root, text = "next", command=lambda: forward(image_number+1))
button_back = Button(root, text = "previous", command = lambda: back(image_number-1))
if image_number == 7:
button_forward = Button(root, text = "next", state = DISABLED)
my_label.grid(row = 0, column = 0, columnspan = 3, rowspan = 25, padx=440, pady= 5)
button_back.grid(row = 23, column = 0)
button_forward.grid(row = 23, column = 2)
pixels.fill((255,0,0))
time.sleep(0.1)
pixels.fill((0,0,0))
time.sleep(0.5)
def back(image_number,):
global my_label
global button_forward
global button_back
my_label.grid_forget()
my_label = Label(image = image_list[image_number-1])
button_forward = Button(root, text = "next", command=lambda: forward(image_number+1))
button_back = Button(root, text = "previous", command = lambda: back(image_number-1))
my_label.grid(row = 0, column = 0, columnspan = 3, rowspan = 25, padx=440, pady= 5)
if image_number == 1:
button_back = Button(root, text = "previous", state = DISABLED)
button_back.grid(row=23, column = 0 )
button_exit.grid(row=23, column = 1 )
button_forward.grid(row=23, column = 2)
pixels.fill((255,0,0))
time.sleep(0.1)
pixels.fill((0,0,0))
time.sleep(0.5)
button_back = Button(root, text = "previous", command = back)
button_exit = Button(root, text = "Exit", command = root.quit)
button_forward = Button(root, text = "next", command =lambda:forward(2))
root.bind('<Left>', back)
root.bind('<Right>', forward)
button_back.grid(row=23, column = 0 )
button_exit.grid(row=23, column = 1 )
button_forward.grid(row=23, column = 2)
root.mainloop()
Your bindings cannot work because the event corresponding to the keypress will be passed instead of the image_number argument in back() and forward().
Also, you are recreating the widgets every time while you should only reconfigure them. So to change the label's image, you can do: my_label.configure(image=<new image>). Also instead of passing image_number as an argument, I would rather use a global variable, so that it will be easier to use the functions in the key bindings:
from tkinter import Tk, Button, Label, DISABLED, NORMAL
from PIL import ImageTk, Image
import board
import time
import neopixel
pixels = neopixel.NeoPixel(board.D18, 30)
root = Tk()
root.configure(bg='black')
root.title("please work")
# define, load, show
my_img1 = ImageTk.PhotoImage(Image.open("1.bmp"))
my_img2 = ImageTk.PhotoImage(Image.open("2.bmp"))
my_img3 = ImageTk.PhotoImage(Image.open("3.bmp"))
my_img4 = ImageTk.PhotoImage(Image.open("4.bmp"))
my_img5 = ImageTk.PhotoImage(Image.open("5.bmp"))
my_img6 = ImageTk.PhotoImage(Image.open("6.bmp"))
my_img7 = ImageTk.PhotoImage(Image.open("7.bmp"))
my_img8 = ImageTk.PhotoImage(Image.open("8.bmp"))
image_list = [my_img1, my_img2, my_img3, my_img4, my_img5, my_img6, my_img7, my_img8]
image_number = 1
# create the label only once
my_label = Label(root, image=image_list[image_number - 1])
my_label.grid(row=0, column=0, columnspan= 3, rowspan=25, padx=440, pady= 5)
def forward(event=None):
global image_number # global variable to keep track of the displayed image
image_number += 1
# change image in label
my_label.configure(image=image_list[image_number - 1])
if image_number == 8:
# last image, disable forward button
button_forward.configure(state=DISABLED)
elif image_number == 2:
# no longer first image, re-enable back button
button_back.configure(state=NORMAL)
pixels.fill((255,0,0))
time.sleep(0.1)
pixels.fill((0,0,0))
time.sleep(0.5)
def back(event=None):
global image_number
image_number -= 1
my_label.configure(image=image_list[image_number - 1])
if image_number == 1:
# first image, disable back button
button_back.configure(state=DISABLED)
elif image_number == 7:
# no longer last image, re-enable forward button
button_forward.configure(state=NORMAL)
pixels.fill((255,0,0))
time.sleep(0.1)
pixels.fill((0,0,0))
time.sleep(0.5)
button_back = Button(root, text="previous", command=back, state=DISABLED)
button_exit = Button(root, text="Exit", command=root.quit)
button_forward = Button(root, text="next", command=forward)
root.bind('<Left>', back)
root.bind('<Right>', forward)
button_back.grid(row=23, column=0)
button_exit.grid(row=23, column=1)
button_forward.grid(row=23, column=2)
root.mainloop()

Python tkinter - label not showing on the 2nd screen

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.

Why does my Tkinter window crash when I try to display a label?

I am using Pycharm and Python 3.8.
My Tkinter window stops responding and causes my program to crash.
Pycharm presents the following line in its output: Process finished with exit code -805306369 (0xCFFFFFFF)
I have the following code for displaying the progress of a for loop:
import tkinter as tk
from tkinter import filedialog, ttk
from tkinter.ttk import Progressbar
import json
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.filename = ''
tk.Button(self, text = 'Upload File', command = self.get_file).grid(row = 0, column = 0)
tk.Button(self, text = 'Verify', command = self.verify).grid(row = 1, column = 0)
# tk.Label(self, text = 'some name').grid(row = 0, column = 1)
self.mainloop()
def get_file(self):
self.filename = tk.filedialog.askopenfilename(title = "Select File", filetypes = [("JSON", "*.json")])
tk.Label(self, text = self.filename).grid(row = 0, column = 1)
def verify():
lbl = tk.Label(self, text = 'Verifying Trustee Public Keys')
lbl.grid(row = 2, column = 0)
prog1 = ttk.Progressbar(self,
length = 100,
orient = "horizontal",
maximum = len(self.data["trustee_public_keys"]),
value = 0)
prog1.grid(row = 3, column = 0)
i = 1
for trustee_key_list in self.data['trustee_public_keys']:
print('Trustee :', i)
//some code
i = i+1
prog1['value'] = i
The get_file part works. But, when I click the verify button to execute the verify() function. The entire window freezes and I get a not responding message.
WHat is the problem with the following part of my code?
lbl = tk.Label(self, text = 'Verifying Trustee Public Keys')
lbl.grid(row = 2, column = 0)
What am I doing wrong?

I want to print my all excel data in new tkinter window using python

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()

iterate through a list and get user response to each item using tkinter GUI

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.

Resources