The problem is the .after() method inside the 'get_content' function. The delay freezes the whole program. I tried solving it with threading but I can't figure it out. I tried a lot of variations. I will just post the code with the last one! Any suggestions? (The code still needs some fixes here and there but the freezing issue is really annoying and I want to get rid of this first)
import random
import tkinter as tk
from sentences import sentences
import threading
from PIL import ImageTk, Image
root = tk.Tk()
root.title("Speed typing test")
root.geometry('700x700')
# Dynamic labels
entry_text = tk.StringVar()
seconds = tk.IntVar()
# Stopwatch
def seconds_counter(*args):
if not entry_text.get():
seconds.set(0)
else:
counter = 0
while counter < 100:
counter += 1
root.update()
root.after(1000)
seconds.set(counter)
global total_time
total_time = counter
if entry_text.get() == sentence:
final = (len(entry.get()) / 5) / (0.1 * total_time)
final_lbl = tk.Label(root, text=f"WPM: {final}")
final_lbl.pack()
entry.delete(0, tk.END)
seconds.set(0)
word_list = sentence.split(' ')
total_words = len(word_list)
total_words_lbl = tk.Label(root, text=f'Total words: {total_words}')
total_words_lbl.pack()
counter = 0
break
x = threading.Thread(target=seconds_counter)
x.start()
sentence = random.choice(sentences)
sentence = sentence.strip('.')
# Create widgets
logo = ImageTk.PhotoImage(Image.open('images/logo.png'))
logo_lbl = tk.Label(image=logo)
sentence_lbl = tk.Label(root, text=sentence)
entry = tk.Entry(root, width=500, textvariable=entry_text)
seconds_lbl = tk.Label(root, textvariable=seconds)
# Place widgets
logo_lbl.pack()
sentence_lbl.pack()
entry.pack()
seconds_lbl.pack()
entry_text.trace('w', seconds_counter)
def stop():
root.destroy()
# command=quit freezes for some reason
btn_quit = tk.Button(root, text='Quit', command=stop)
btn_quit.pack()
root.mainloop()
Related
**I am writing a baseball counting program. I have a label for walks and strikeouts. To the side of those labels I have buttons with the text "+1". I want the buttons to be able to change and print the number of walks and strikeouts every time I click the +1 buttons. I just need some ideas to help get started. Here is my code for clarification: **
import tkinter as tk
from tkinter.constants import COMMAND, X
global walk_counter
walk_counter = 0
global strikeout_counter
strikeout_counter = 0
def main(): # This is the main function
root = tk.Tk()
frame = tk.Frame(root)
frame.master.title("Random Title")
frame.pack(padx=4, pady=3, fill=tk.BOTH, expand=1)
populate_boxes(frame)
root.mainloop()
def populate_boxes(frame):
walks_label = tk.Label(frame, text="BB:")
walks_entry = tk.Label(frame, width=4)
walks_button = tk.Button(frame,text="+1")
strikeouts_label = tk.Label(frame,text="Strikeouts:")
strikeouts_entry = tk.Label(frame,width=4)
strikeouts_button = tk.Button(frame,text="+1")
walks_label.place(x=200,y=500)
walks_entry.place(x=250,y=500)
walks_button.place(x=300,y=500)
strikeouts_label.place(x=400,y=500)
strikeouts_entry.place(x=450,y=500)
strikeouts_button.place(x=500,y=500)
def add_more_walks():
global walk_counter
walk_counter += 1
walks_entry.config(text = walk_counter)
add_more_walks()
main()
I am creating a math game and want a score count in the top corner.
Yes, you need the command argument, but you also need a function for the command argument to run. Something like this would work:
from tkinter import *
def increment_score():
global score
score += 1 # update variable
score_addition_easy_number.config(text=score) # update screen
root = Tk()
score = 0
root7 = Frame(root)
score_addition_easy_label = Label(root7, text="Score count: ")
score_addition_easy_label.pack(side=LEFT)
score_addition_easy_number = Label(root7, text=score)
score_addition_easy_number.pack(side=LEFT)
root7.pack()
a_e_answer_2 = Button(root, text="8", font=("times", 30, "bold"), padx=190, command=increment_score)
a_e_answer_2.pack()
root.mainloop()
Im making this game called:
IDLE PEN ,(MAKE PENS)
and every 1 second i get a bonus pen
how i get a bonus pen is doing this
Import time
While true
make a pen()
time.sleep(1)
but i have some code under the while true loop.
the code under the while true loop is like buttons to
upgrade the pens or make a pen
So how do i make the code under the while true loop work?
This is my game im happy for anyone to copy it
its not ready yet
import functools
import tkinter
import tkinter.messagebox
import time
from random import seed
from random import randint
# eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
window = tkinter.Tk()
window.title('Idle Pen')
def print_pen(number: int):
return f"Pens: {number}"
class pencount:
def __init__(self):
self.pencount = 0
self.text = tkinter.Text(height=1, width=30)
self.text.insert("1.0", print_pen(0))
self.text['state'] = 'disabled'
self.text.pack()
def changepencount(self, count):
if self.pencount + count < 0:
return
self.pencount = self.pencount + count
self.text['state'] = 'normal'
self.text.delete("1.0", "end")
self.text.insert("1.0", print_pen(self.pencount))
self.text['state'] = 'disabled'
self.text.pack()
pen = pencount()
changepenup = functools.partial(pen.changepencount, 1)
B = tkinter.Button(window, text="Make Pen", command=changepenup)
changependown = functools.partial(pen.changepencount, -100)
A = tkinter.Button(window, text='Penmaker', command=changependown)
Q = tkinter.Button(window, text="Quit", command=window.destroy)
U = tkinter.Button
# eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
B.pack()
A.pack()
Q.pack()
window.mainloop()
You could use threading to run your loop in separated thread and then main thread may run tkitner
OR you can use tkinter function after() (instead of while True) to run function with delay and this function should use again after() to run itself.
import tkinter as tk
# --- functions ---
def update():
global value
value += 1
text = f'make penny: {value}'
print(text)
label['text'] = text
# run again after 1s (1000ms)
root.after(1000, update)
# --- main ---
value = 0
root = tk.Tk()
label = tk.Label(root, text="make penny: 0")
label.pack()
button = tk.Button(root, text="Exit", command=root.destroy)
button.pack()
# run first time after 1s (1000ms)
root.after(1000, update)
root.mainloop()
I'm trying to create a programm that reads ANT signals and displays them in a TKinter window.
To display the changing values, I'm updating labels (in an infinite loop),which works so far, but whenever I try to move the window, the program crashes (no response).
So here's what the (final program) should do:
Receive and store the ANT data, which I read with another file (which gives me
power and cadence)
Round the numbers to 2-3 decimals (max)
Read the total power output so far from a file
Write the power data in a file (append)
Sum the total power output
display the current speed, cadence, power and total power output
My Code:
# imports
import random
import time
from tkinter import *
# creating root tkinter Window
root = Tk()
root.title("ANT+ Live Data")
# defining Text Variables
running = 0
SAVE_FILE = "power_doc.txt"
HEADLINE_TEXT = StringVar()
HEADLINE_TEXT.set('')
HEADLINE_M = StringVar()
HEADLINE_M.set('')
power_display = StringVar()
power_display.set('0')
cadence_display = StringVar()
cadence_display.set('0')
speed_display = StringVar()
speed_display.set('0')
powertotal_display = StringVar()
powertotal_display.set('0')
# defining Window Size
root.geometry("800x600")
# creating Label Frame to wrap labels
frame = LabelFrame(root)
frame.pack(padx=20, pady=20)
# creating labels, Headline 1
slabel = Label(root, font = ("Helvetica",48) ,textvariable = HEADLINE_M, justify=CENTER, bg="#FFFFFF", fg = '#000000')
slabel.pack(fill=BOTH, padx=20, pady=10)
# headline 2
headLine = Label(root, font=("Helvetica", 26), textvariable= HEADLINE_TEXT, justify=CENTER, bg="#FFFFFF", fg = '#000000')
headLine.pack(fill=BOTH, pady=5)
# power
l1 = Label(root, font = ("Helvetica",20) ,textvariable = power_display, justify=CENTER, bg="#190000", fg = '#B0C4C2')
l1.pack(fill=BOTH)
# cadence
l2 = Label(root, font = ("Helvetica",20), textvariable = cadence_display, justify=CENTER, bg="#190000", fg = '#B0C4C2')
l2.pack(fill=BOTH)
# speed
l3 = Label(root, font = ("Helvetica",20), textvariable = speed_display, justify=CENTER, bg="#190000", fg = '#B0C4C2')
l3.pack(fill=BOTH)
# total Power
l4 = Label(root, font = ("Helvetica",20), textvariable = powertotal_display, justify=CENTER, bg="#190000", fg = '#B0C4C2')
l4.pack(fill=BOTH)
# function to read total power values out of a file
def get_power_total(SAVE_FILE):
power_total = 0
with open(SAVE_FILE, 'r') as inp:
for line in inp:
try:
num = float(line)
power_total += num
except ValueError:
print('{} is not a number!'.format(line))
power_total = round_number(power_total)
return power_total
# generate random Numbers for testing purposes
def randomize_number(inputNumber):
inputNumber = float(inputNumber)*random.uniform(0.99, 1.01)
inputNumber = round_number(inputNumber)
return inputNumber
# rounds numbers to 2 decimals
def round_number(inputNumber):
inputNumber = round(inputNumber, 2)
return inputNumber
# use formula for a 28" Wheel to determine Speed using cadence
def determine_speed(cadence):
speed = float(cadence)*0.356
speed = round_number(speed)
return speed
def get_power(cadence):
power = float(cadence)*0.8
power = round_number(power)
return power
# dummy function to test-print Values, redundant in current state
def print_values(x1, x2, x3):
print("Leistung: {} W Trittfrequenz: {} Geschwindigkeit: {} Km/H" .format(x1, x2, x3))
# write in document to determine total power output
def write_file(SAVE_FILE, power):
f = open(SAVE_FILE, "a+")
f.write(str(power) + '\n')
f.close()
def update_label():
power_total = get_power_total(SAVE_FILE)
cadence = int(50)
cadence = randomize_number(cadence)
root.after(100)
power = get_power(cadence)
root.after(100)
speed = determine_speed(cadence)
root.after(100)
power_total += power
write_file(SAVE_FILE, power)
power_display.set("Leistung: {} W".format(power))
cadence_display.set("Trittfrequenz: {}".format(cadence))
speed_display.set("Geschwindigkeit : {} Km/h".format(speed))
powertotal_display.set("Gesamtleistung seit 10 Uhr: {} W".format(power_total))
root.after(1000)
root.update_idletasks()
# mainloop to display the window
while True:
root.after(1000, update_label())
root.mainloop()
This is basically just a draft to import the ANT data, hence there are some numbers being randomly generated to show if the label update function works.
I'm fairly new to coding with Python (or coding at all), so I'm pretty sure there are other issues with my code as well, but perhaps someone has a suggestion on how to solve my issue.
Any help or suggestions are appreciated.
Cheers in advance!
Edit: Solved! thanks Jason!
Changes were to be made here:
def update_label():
power_display.set("Leistung: {} W".format(power))
cadence_display.set("Trittfrequenz: {}".format(cadence))
speed_display.set("Geschwindigkeit : {} Km/h".format(speed))
powertotal_display.set("Gesamtleistung seit 10 Uhr: {} W".format(power_total))
root.after(1000, update_label)
root.update_idletasks()
root.after(1000, update_label)
root.mainloop()
What is wrong with this program? Every time I run it the first math problem is show before I push start. Also the answer is always the first math problem, it never changes. Also there should not be a math problem above the timer. Thanks, Scott
from Tkinter import*
import time
import tkMessageBox
import random
def Questions():
number1 = random.randrange(1,25)
number2 = random.randrange(1,50)
answer = number1 + number2
prompt = ("Add " + str(number1) + " and " + str(number2))
label1 = Label(root, text=prompt, width=len(prompt), bg='yellow')
label1.pack()
return answer
def start():
global count_flag
Questions()
count_flag = True
count = 0.0
while True:
if count_flag == False:
break
# put the count value into the label
label['text'] = str(count)
# wait for 0.1 seconds
time.sleep(0.1)
# needed with time.sleep()
root.update()
# increase count
count += 0.1
def Submit(answer, entryWidget):
""" Display the Entry text value. """
global count_flag
count_flag = False
print answer
if entryWidget.get().strip() == "":
tkMessageBox.showerror("Tkinter Entry Widget", "Please enter a number.")
if answer != int(entryWidget.get().strip()):
tkMessageBox.showinfo("Answer", "INCORRECT!")
else:
tkMessageBox.showinfo("Answer", "CORRECT!")
# create a Tkinter window
root = Tk()
root.title("Math Quiz")
root["padx"] = 40
root["pady"] = 20
# Create a text frame to hold the text Label and the Entry widget
textFrame = Frame(root)
#Create a Label in textFrame
entryLabel = Label(textFrame)
entryLabel["text"] = "Answer:"
entryLabel.pack(side=LEFT)
# Create an Entry Widget in textFrame
entryWidget = Entry(textFrame)
entryWidget["width"] = 50
entryWidget.pack(side=LEFT)
textFrame.pack()
#directions
directions = ('Click start to begin. You will be asked a series of questions.')
instructions = Label(root, text=directions, width=len(directions), bg='orange')
instructions.pack()
# this will be a global flag
count_flag = True
answer = Questions()
Sub = lambda: Submit(answer, entryWidget)
#stopwatch = lambda: start(answer)
# create needed widgets
label = Label(root, text='0.0')
btn_submit = Button(root, text="Submit", command = Sub)
btn_start = Button(root, text="Start", command = start)
btn_submit.pack()
btn_start.pack()
label.pack()
# start the event loop
root.mainloop()
Your problem is with how you're calling the Questions() method. You only ask for the answer once with
answer = Questions()
and you do this before you press start (which is why it shows up before you hit start)
To fix it you could use code like this:
from Tkinter import*
import time
import tkMessageBox
import random
def Questions():
number1 = random.randrange(1,25)
number2 = random.randrange(1,50)
answer = number1 + number2
prompt = ("Add " + str(number1) + " and " + str(number2))
label1 = Label(root, text=prompt, width=len(prompt), bg='yellow')
label1.pack()
return answer
def start():
global count_flag
global answer
answer = Questions()
count_flag = True
count = 0.0
while True:
if count_flag == False:
break
# put the count value into the label
label['text'] = str(count)
# wait for 0.1 seconds
time.sleep(0.1)
# needed with time.sleep()
root.update()
# increase count
count += 0.1
def Submit(answer, entryWidget):
""" Display the Entry text value. """
global count_flag
count_flag = False
print answer
if entryWidget.get().strip() == "":
tkMessageBox.showerror("Tkinter Entry Widget", "Please enter a number.")
if answer != int(entryWidget.get().strip()):
tkMessageBox.showinfo("Answer", "INCORRECT!")
else:
tkMessageBox.showinfo("Answer", "CORRECT!")
# create a Tkinter window
root = Tk()
root.title("Math Quiz")
root["padx"] = 40
root["pady"] = 20
# Create a text frame to hold the text Label and the Entry widget
textFrame = Frame(root)
#Create a Label in textFrame
entryLabel = Label(textFrame)
entryLabel["text"] = "Answer:"
entryLabel.pack(side=LEFT)
# Create an Entry Widget in textFrame
entryWidget = Entry(textFrame)
entryWidget["width"] = 50
entryWidget.pack(side=LEFT)
textFrame.pack()
#directions
directions = ('Click start to begin. You will be asked a series of questions.')
instructions = Label(root, text=directions, width=len(directions), bg='orange')
instructions.pack()
# this will be a global flag
count_flag = True
Sub = lambda: Submit(answer, entryWidget)
#stopwatch = lambda: start(answer)
# create needed widgets
label = Label(root, text='0.0')
btn_submit = Button(root, text="Submit", command = Sub)
btn_start = Button(root, text="Start", command = start)
btn_submit.pack()
btn_start.pack()
label.pack()
# start the event loop
root.mainloop()
In this code the answer is updated every time you hit start and only updates when you hit start.