Trouble with making a updating loading bar (Label) in Tkinter - python

I am making a percentage updating Loading bar(Label) which should automatically start when my program has started. When the 'Loading bar' hits 100%, the 'Loading bar' should be removed, and the rest of the program should continue, although when I am starting the program, the window does not respond until about 5 seconds.
number = 0
number1 = str(number)
Labe = tk.Label(root, width=10,bd=1, bg="#ADA5A5", font=("Arial Bold", 36), fg="White")
Labe.grid(row=0, column=0)
def work():
global number1
Labe['text'] = "Loading" + " " + number1 + "%"
global number
number = number + 1
number1 = str(number)
if number == 102:
root.after(1000)
print("end")
Labe.grid_remove()
num = 101
for x in range(num):
print("He")
root.after(50, work)
root.after(50)
#Adding stuff to root
rootHelloLabel = tk.Label(root, text="Ordering system, please sign in", bg="#7271AD",
fg="White", font=("Arial Bold", 40), width=48, height=2)
placeholder = tk.Label(root, text="", pady=20, bg="#ACAD71")
placeholder.grid(row=0, column=0)
rootHelloLabel.grid(row=1, column=0)
placeholder1 = tk.Label(root, text="", pady=70, bg="#ACAD71")
placeholder1.grid(row=2, column=0)
loginButton = tk.Button(root, pady=30, padx=80, text="Login", font=("Arial Bold", 27),
bg="#71AD90", fg="#D0CFD1", command=login)
loginButton.grid(row=3, column=0)
adminButton = tk.Button(root, pady = 10, padx = 40, text="Admin",
font=("Arial Bold", 27), bg="#71AD90", fg="#D0CFD1")
adminButton.grid(row=5, column=0)

I made three small changes and I think it works.
number = 0
number1 = str(number)
Labe = tk.Label(root, width=10,bd=1, bg="#ADA5A5", font=("Arial Bold", 36), fg="White")
Labe.grid(row=0, column=0)
def work():
global number1
Labe['text'] = "Loading" + " " + number1 + "%"
global number
number = number + 1
number1 = str(number)
if number == 102:
root.after(1000)
print("end")
Labe.grid_remove()
num = 101
for x in range(num):
print("He")
root.after(50, work)
root.after(50)
root.update() # added this so the window displays for one frame
# it's similar to mainloop() but only runs once
#Adding stuff to root
rootHelloLabel = tk.Label(root, text="Ordering system, please sign in", bg="#7271AD",
fg="White", font=("Arial Bold", 40), width=48, height=2)
placeholder = tk.Label(root, text="", pady=20, bg="#ACAD71")
placeholder.grid(row=0, column=0)
rootHelloLabel.grid(row=1, column=0)
placeholder1 = tk.Label(root, text="", pady=70, bg="#ACAD71")
placeholder1.grid(row=2, column=0)
loginButton = tk.Button(root, pady=30, padx=80, text="Login", font=("Arial Bold", 27),
bg="#71AD90", fg="#D0CFD1", command=lambda: login())
loginButton.grid(row=3, column=0) # added lambda function so this only runs when clicked
adminButton = tk.Button(root, pady = 10, padx = 40, text="Admin",
font=("Arial Bold", 27), bg="#71AD90", fg="#D0CFD1")
adminButton.grid(row=5, column=0)
root.mainloop() # added this so that the program runs when done (can remove aswell)
I hope this works for you. I didnt quite understand the question but once I added the update() function it worked fine and I realised what you mean by a loading bar. I hope this helps!

You runs 100 times after(50) in for-loop so it can stop program for 5 second. And I don't know if you really need it.
And I would run after(50, work) directly in work
def work():
global number # PEP8: all `global` at the beginning of function
labe['text'] = f"Loading {number}%"
number += 1
if number > 100:
root.update() # to update last text in label because `after(1000)` will block it
root.after(1000)
print("end")
labe.grid_remove()
else:
root.after(50, work)
Full working code (with other changes):
PEP 8 -- Style Guide for Python Code
import tkinter as tk
# --- functions --- # PEP8: all functions directly after imports (and after all classes)
def work():
global number # PEP8: all `global` at the beginning of function
labe['text'] = f"Loading {number}%"
number += 1
if number > 100:
root.update() # to update last text in label because `after(1000)` will block it
root.after(1000)
print("end")
labe.grid_remove()
else:
# run again
root.after(50, work)
def login():
pass
# --- main ---
number = 0
root = tk.Tk()
labe = tk.Label(root, width=10, bd=1, bg="#ADA5A5", font=("Arial Bold", 36), fg="White")
labe.grid(row=0, column=0)
root_hello_label = tk.Label(root, text="Ordering system, please sign in", bg="#7271AD",
fg="White", font=("Arial Bold", 40), width=48, height=2)
root_hello_label.grid(row=1, column=0)
placeholder1 = tk.Label(root, text="", pady=20, bg="#ACAD71")
placeholder1.grid(row=0, column=0)
placeholder2 = tk.Label(root, text="", pady=70, bg="#ACAD71")
placeholder2.grid(row=2, column=0)
login_button = tk.Button(root, pady=30, padx=80, text="Login", font=("Arial Bold", 27),
bg="#71AD90", fg="#D0CFD1", command=login)
login_button.grid(row=3, column=0)
admin_button = tk.Button(root, pady = 10, padx = 40, text="Admin",
font=("Arial Bold", 27), bg="#71AD90", fg="#D0CFD1")
admin_button.grid(row=5, column=0)
# run first time
root.after(50, work)
root.mainloop()
EDIT:
If you need to run with for-loop then you should rather set different times in after(..., work)
for i in range(1, 102):
root.after(50*i, work)
Full working code:
import tkinter as tk
# --- functions --- # PEP8: all functions directly after imports (and after all classes)
def work():
global number # PEP8: all `global` at the beginning of function
labe['text'] = f"Loading {number}%"
number += 1
if number > 100:
root.update() # to update last text in label because `after(1000)` will block it
root.after(1000)
print("end")
labe.grid_remove()
def login():
pass
# --- main ---
number = 0
root = tk.Tk()
labe = tk.Label(root, width=10, bd=1, bg="#ADA5A5", font=("Arial Bold", 36), fg="White")
labe.grid(row=0, column=0)
root_hello_label = tk.Label(root, text="Ordering system, please sign in", bg="#7271AD",
fg="White", font=("Arial Bold", 40), width=48, height=2)
root_hello_label.grid(row=1, column=0)
placeholder1 = tk.Label(root, text="", pady=20, bg="#ACAD71")
placeholder1.grid(row=0, column=0)
placeholder2 = tk.Label(root, text="", pady=70, bg="#ACAD71")
placeholder2.grid(row=2, column=0)
login_button = tk.Button(root, pady=30, padx=80, text="Login", font=("Arial Bold", 27),
bg="#71AD90", fg="#D0CFD1", command=login)
login_button.grid(row=3, column=0)
admin_button = tk.Button(root, pady = 10, padx = 40, text="Admin",
font=("Arial Bold", 27), bg="#71AD90", fg="#D0CFD1")
admin_button.grid(row=5, column=0)
# 102-1 = 101 loops, because it needs to display values 0...100 which gives 101 values
for i in range(1, 102):
root.after(50*i, work)
root.mainloop()
EDIT:
Because after(1000) freezes all GUI for 1 second so it it better to use after(1000, remove_label) to execute other function after 1 second and this doesn't freeze GUI.
def work():
global number
labe['text'] = f"Loading {number}%"
number += 1
if number > 100:
root.after(1000, remove_label)
else:
root.after(50, work)
def remove_label():
print("end")
labe.grid_remove()

Related

How do I get the user to click on the random button (1,10) in order to guess which button has diamond hidden? User has got 3 attempts

A user has got 10 buttons and the diamond is hidden in one by using random function.
User has got three attempts to find out in which box is the diamond.
from tkinter import *
import tkinter.messagebox as msgBox
window = Tk()
window.title("Find the diamond")
window.configure(bg="gray", pady=100)
window.geometry("720x420")
window.resizable(0,0)
number_of_guesses = 0
random_box_number = (1,10)
HideTheDiamond = Button(window, text = "Hide the diamond", bg ="green")
import random
import sys
Button1 = Button(window, text = "1", width=10,height=3, bg="yellow")
Button2 = Button(window, text = "2",width=10,height=3, bg="blue")
Button3 = Button(window, text = "3",width=10,height=3, bg="dark red")
Button4 = Button(window, text = "4",width=10,height=3, bg="green")
Button5 = Button(window, text = "5", width=10,height=3, bg="red")
Button6 = Button(window, text = "6",width=10,height=3, bg="purple")
Button7 = Button(window, text = "7",width=10,height=3, bg="brown")
Button8 = Button(window, text = "8",width=10,height=3, bg="orange")
Button9 = Button(window, text = "9",width=10,height=3, bg="dark blue")
Button10 = Button(window, text = "10", width=10,height=3, bg="pink")
label11=Label(window,text="Click the Hid the diamond button to start the game. \n Then,
click on the box where you think the diamond is.\n You have three guesses to find
it.",bg="gray")
Button1.grid(row=1, column=1, padx=10, pady=10,sticky=W)
Button2.grid(row=1, column=2,padx=10, pady=10, sticky=W)
Button3.grid(row=1, column=3,padx=10, pady=10, sticky=W)
Button4.grid(row=1, column=4, padx=10, pady=10, sticky=W)
Button5.grid(row=1, column=5, padx=10, pady=10, sticky=W)
Button6.grid(row=2, column=1, padx=10, pady=10, sticky=W)
Button7.grid(row=2, column=2, padx=10, pady=10, sticky=W)
Button8.grid(row=2, column=3, padx=10, pady=10, sticky=W)
Button9.grid(row=2, column=4,padx=10, pady=10, sticky=W)
Button10.grid(row=2, column=5,padx=10, pady=10, sticky=W)
label11.grid(row =5, column =2, sticky=W)
HideTheDiamond.grid(row=5, column =5)
HideTheDiamond.configure(state=NORMAL)
label11.configure(width=40, height=10)
Button1.configure(state=DISABLED)
Button2.configure(state=DISABLED)
Button3.configure(state=DISABLED)
Button4.configure(state=DISABLED)
Button5.configure(state=DISABLED)
Button6.configure(state=DISABLED)
Button7.configure(state=DISABLED)
Button8.configure(state=DISABLED)
Button9.configure(state=DISABLED)
Button10.configure(state=DISABLED)
import random
#staticmethod
def random(self):
global_number_of_guesses = 0
global_box_number = random.randint(1, 10)
return global_box_number
HideTheDiamond.configure(command=random)
def connect():
Button1.configure(state=NORMAL)
Button2.configure(state=NORMAL)
Button3.configure(state=NORMAL)
Button4.configure(state=NORMAL)
Button5.configure(state=NORMAL)
Button6.configure(state=NORMAL)
Button7.configure(state=NORMAL)
Button8.configure(state=NORMAL)
Button9.configure(state=NORMAL)
Button10.configure(state=NORMAL)
HideTheDiamond.configure(state=DISABLED)
connnecting box_number to button
def box_number(self):
self.box_number = box_number
return box_number()
HideTheDiamond.configure(command=connect)
def checkGuess():
if box_number == random:
number_of_guesses += 1
print("you have guessed the number")
else:
print("wrong.two more attemps left")
if number_of_guesses == 3:
print("you lost")
checkGuess()
window.mainloop()
global_number_of_guesses equals to three
global_box_number is random number or box system uses to hide the diamond in
box_number is the box user clicks on in order to find out if diamond is in there
from tkinter import *
import random
window = Tk()
global guesses
guesses = 0
def start_game():
global location
location = random.randrange(1, 11, 1)
def clicked(button_number):
global guesses, location
guesses += 1
if guesses > 3:
# tell the player he lost here in any way you like
print("you lost")
else:
if button_number == location:
# Tell the player he won
print("You won")
else:
# The player guessed wrong but can try again...
print("Not correct, sorry")
for i in range(1, 11):
Button(window, command=lambda i=i: clicked(i).grid(row=i//5, column=i%5, sticky='nswe'))
b11 = Button(window, text="Click here to start the game", command=start_game)
b11.grid()
window.mainloop()
Not the best solution but it should work.
I hope this provides some help, let me know if there are any problems with this.

Trying to make a GUI tkinter that generates a random number, takes the user's guess and compare it, then takes the user's bet in one button

I'm new to python and right now I'm trying to make a GUI Tkinter that gives a random integer from 1-9 then I would take an entry from the user and his bet, if the user's guess is correct then his bet would be added to his money(money = 1000), and if wrong, it would subtract the bet from his money and all of it has to be done in one button. My problem is that with my code the first comparing would be correct but then after that it would always be false like it doesn't read my if-else statement anymore. And the variable money which has a value of 1000 always resets the second time I clicked the button, like for the first time, if the bet is 500 and the guess is correct, it would add but after that it would always reset, instead of the number being 2000 after the second guess, it would start again at 1500 like it doesn't change the original variable.
I don't know what should I do, please help.
import tkinter as tk
import random
window = tk.Tk()
window.title("Guessing Game")
window.geometry("600x600")
window.configure(bg="Orange")
num = random.randint(1, 9)
def my_guess():
guess = int(txtGuess.get())
bet = int(txtBet.get())
money = 1000
if guess == num:
money = money + bet
lblBet.config(text=money)
lblNumber.config(text=random.randint(1, 9))
else:
money = money - bet
lblBet.config(text=money)
lblNumber.config(text=random.randint(1, 9))
lblNumber = tk.Label(window, text=num, fg="blue", bg="Violet", font=("Bold", 25), width=5,
height=2)
lblNumber.place(x=30, y=180)
lblRandom = tk.Label(window, text="Random", fg="indigo", bg="black", font=("Bold", 25),
width=8, height=2)
lblRandom.place(x=10, y=20)
lblMoney = tk.Label(window, text="Money", fg="indigo", bg="black", font=("Bold", 25), width=8,
height=2)
lblMoney.place(x=210, y=20)
lblBet = tk.Label(window, text="1000", fg="blue", bg="Violet", font=("Arial", 27), width=8,
height=2)
lblBet.place(x=210, y=180)
lblGuess = tk.Label(window, text="Guess", fg="indigo", bg="black", font=("Bold", 25), width=8,
height=2)
lblGuess.place(x=410, y=20)
txtGuess = tk.Entry(window, text="", fg="blue", bg="Violet", font=("Arial", 25), width=8)
txtGuess.place(x=410, y=180)
txtBet = tk.Entry(window, text="", fg="blue", bg="Violet", font=("Arial", 15), width=20)
txtBet.place(x=195, y=400)
btnBet = tk.Button(window, text="Bet", font=("Arial", 15), width=20)
btnBet.place(x=195, y=450)
window.mainloop()
You forgot the basics. You need to add a command option to run the function when button is clicked -
btnBet = tk.Button(window, text="Bet", font=("Arial", 15), width=20,command=my_guess)
Note - You should not add () here when using command.
You can add it if you used lambda, for e.g - command=lambda:my_guess()
The problem is that you set the money to 1000 inside the guess function, the money value should be extracted from the lblBet label. Also the num should also be extraded from the random label.
The updated guess function:
def my_guess():
guess = int(txtGuess.get())
bet = int(txtBet.get())
money = int(lblBet["text"])
num = int(lblNumber["text"])
if guess == num:
money = money + bet
lblBet.config(text=money)
lblNumber.config(text=random.randint(1, 9))
else:
money = money - bet
lblBet.config(text=money)
lblNumber.config(text=random.randint(1, 9))
You also need to add the guess function to the button.
btnBet = tk.Button(window, text="Bet", font=("Arial", 15), width=20, command=my_guess)

How to print into python tkinter entry field by pressing a button?

So, i'm trying to create a program that creates a random number (using randint) to an entry field, when a button is pressed. But I can't figure out how to do it.
import tkinter
from tkinter import Entry, END, E
from random import randint
root = tkinter.Tk()
root.title('Number Generator')
e = Entry(root, font=("LEMON MILK Bold", 24), width=15, borderwidth=10)
e.grid(row=0, column=0, columnspan=3, padx=50, pady=50)
e.delete(0, END)
e.insert(0, number)
number=print(randint(0, 100))
#Definitions
def button_generate():
print(number)
#Buttons
button_generate = tkinter.Button(root, text="Random number", font=("LEMON MILK Bold", 24), padx=10,
pady=10, command=button_generate)
button_exit = tkinter.Button(root, text="Exit", font=("LEMON MILK Bold", 14), padx=5, pady=5,
command=root.quit)
#Grid
button_generate.grid(row=1, column=0, columnspan=3)
button_exit.grid(row=2, column=2, sticky=E)
root.mainloop()
So basically how can I make the random number print into the entry field? (Right now it is not printing anywhere due to my bad code)
Please check this out
from tkinter import *
from random import randint
def set_text():
number=randint(0, 100)
e.delete(0,END)
e.insert(0,number)
print(number)
win = Tk()
e = Entry(win,width=10)
e.pack()
b1 = Button(win,text="Gen",command=set_text)
b1.pack()
win.mainloop()

How to update Labels in tkinter?

I'm trying to create a program in where you put a word in a box, press add, and this word goes to a list, which is also displayed on the right side. When I press the forward button the first thing on the list is deleted. Problem is I can't get the labels to update when I press the buttons / edit the list.
from tkinter import *
root = Tk()
root.title('Speakers List')
root.minsize(800, 600)
speakers = ['none']
spe = speakers[0]
def add():
if spe == 'none':
speakers.insert(0, [s])
e.delete(0, END)
spe.config(text=speakers[0])
else:
speakers[-2] = [s]
e.delete(0, END)
spe.config(text=speakers[0])
return
def forward():
if len(speakers) is 0:
return
else:
del speakers[0]
spe.config(text=speakers[0])
return
entry = StringVar()
e = Entry(root, width=30, font=("Arial", 20), textvariable=entry)
e.grid(row=0, sticky=W)
s = e.get()
button1 = Button(root, padx=10, pady=10, bd=5, text='Add', fg='black', command=add)
button1.grid(row=0, column=1)
button2 = Button(root, padx=10, pady=10, bd=5, text='Next', fg='black', command=forward)
button2.grid(row=1, column=1)
n = Label(root, font=("Arial", 35), bd=2, text=spe)
n.grid(row=1, sticky=W)
listdisplay = Label(root, font=('Arial', 20), text=speakers)
listdisplay.grid(row=0, column=10)
root.mainloop()
Is this the sort of thing you were looking for ?
from tkinter import *
root = Tk()
root.title('Speakers List')
root.minsize(800, 600)
speakers = ['50']
spe = speakers[0]
def add():
entry=e.get()
speakers.append(entry)
listdisplay.config(text=speakers)
return
def forward():
if len(speakers) is 0:
return
else:
del speakers[0]
listdisplay.config(text=speakers)
spe=speakers[0]
n.config(text=spe)
return
entry = StringVar()
e = Entry(root, width=30, font=("Arial", 20), textvariable=entry)
e.grid(row=0, sticky=W)
s = e.get()
button1 = Button(root, padx=10, pady=10, bd=5, text='Add', fg='black',command=add)
button1.grid(row=0, column=1)
button2 = Button(root, padx=10, pady=10, bd=5, text='Next', fg='black',command=forward)
button2.grid(row=1, column=1)
n = Label(root, font=("Arial", 35), bd=2, text=spe)
n.grid(row=1, sticky=W)
listdisplay = Label(root, font=('Arial', 20), text=speakers)
listdisplay.grid(row=0, column=10)
root.mainloop()
If so:
You create a list and then you use the append function to add an item to it. The rest was pretty much right.

Need some help in creating a tkinter countdown

I am trying to create a timer in tkinter. It count down from set time and then output "Time is up". I have written most of my code. I also have inserted a logging system, so I can work over some errors, which are recorded into a log file.
Code:
from tkinter import *
import logging
logging.basicConfig(filename='timer_err.log',format='%(levelname)s:%(message)s',level=logging.DEBUG)
main = Tk()
main.wm_attributes("-fullscreen",True)
main.wm_attributes("-transparentcolor","darkgreen")
main.title("Timer")
main.config(background="orange")
timerun = 0
comp = 0
secs = DoubleVar()
mins = IntVar()
hrs = IntVar()
def ok():
global timerun
try:
comp = float(float(secs.get())+int(mins.get()*60)+int(hrs.get()*3600))
done.config(state="disabled")
logging.info(("\t{} - Program launched").format(asctime(localtime())))
while timerun < comp:
timerun = clock()
disp.config(state="normal")
disp.insert(0, str(round(comp-timerun, 3)))
main.update()
disp.delete(0, END)
disp.config(state="readonly")
disp.config(state="normal")
disp.insert(0, "Time is up!")
disp.config(state="readonly")
main.update()
def end(self):
main.destroy()
logging.info(("\t{} - Program successfully terminated").format(asctime(localtime())))
main.bind("<Escape>",end)
except Exception as e:
logging.debug(("\t{} - {}").format(asctime(localtime()),str(e)))
logging.warning(("\t{} - {}").format(asctime(localtime()),str(e)))
pass
finally:
logging.info(("\t{} - Program stopped").format(asctime(localtime())))
dispframe = Frame(main, bg="orange")
dispframe.pack(fill="both")
disp = Entry(dispframe, fg="black", bg="lightgray", font=("Arial", 100, "bold"), bd=0, state="readonly", takefocus=False, readonlybackground="lightgray", selectforeground="white", selectbackground="navy")
disp.pack(fill="x", pady=12, side="left")
setframe = Frame(main, bg="orange")
setframe.pack(fill="both")
seconds = Spinbox(setframe, fg="red", bg="yellow", from_=0, to=59.5, increment=0.5, font=("Arial", 100, "bold"), bd=0, state="readonly", takefocus=True, readonlybackground="yellow", buttonbackground="green", selectforeground="white", selectbackground="navy", wrap=True, textvariable=secs)
seconds.pack(fill="x", pady=12)
minutes = Spinbox(setframe, fg="red", bg="yellow", from_=0, to=59, font=("Arial", 100, "bold"), bd=0, state="readonly", takefocus=True, readonlybackground="yellow", buttonbackground="green", selectforeground="white", selectbackground="navy", wrap=True, textvariable=mins)
minutes.pack(fill="x", pady=12)
hours = Spinbox(setframe, fg="red", bg="yellow", from_=0, to=99999, font=("Arial", 100, "bold"), bd=0, state="readonly", takefocus=True, readonlybackground="yellow", buttonbackground="green", selectforeground="white", selectbackground="navy", wrap=True, textvariable=hrs)
hours.pack(fill="x", pady=12)
okframe = Frame(main, bg="orange")
okframe.pack(fill="both")
done = Button(okframe, fg="red", bg="yellow", text="Done", font=("Arial", 100, "bold"), bd=0, activeforeground="red", activebackground="yellow", underline=1, command=ok)
done.pack(fill="x", pady=12)
from time import *
main.mainloop()
Could someone help me to create a "Reset" button, which sets time back to 0?
Or at least give me a slight advice to me on how to do that. Thank you.

Categories