So Here i have a function:
def test():
global value
if value ==0:
value=1
return True
else:
value=0
return False
Here is what I come up with:
import tkinter as tk
value=0
while True:
root = tk.Tk()
root.title("my title")
root.geometry('200x150')
root.configure(background='black')
clock_frame = tk.Label(root, font = ('caviar dreams', 130), bg='black')
clock_frame.pack()
def test():
global value
if value ==0:
value=1
return True
else:
value=0
return False
if test() is True:
clock_frame.config(text="HelloWorld",fg="red")
else:
clock_frame.config(text="HelloWorld",fg="white")
root.mainloop()
I want to display the result of this in a Tkinter GUI. I want to change a label while the function is True or False. I want this change to happen every second.
But i don't know how to do it.
Thank you
You can use after() to periodically call test() and update the label:
import tkinter as tk
root = tk.Tk()
root.geometry('+100+100')
root.config(bg='black')
clock = tk.Label(root, text='HelloWorld', font=('caviar dreams', 130), bg='black')
clock.pack()
value = 0
def test():
global value
value = 1 - value
return value == 1
def update():
color = 'red' if test() else 'white'
clock.config(fg=color)
root.after(1000, update) # call update() after 1 second
update() # start the periodic update
root.mainloop()
Use the after method then. The syntax is like this: widget.after(milisecond, action). First you add the time to wait and next you add the action to do.
help this is result recurs like this
Total Account: 13
Total Account: 13
def update():
file = open("list.txt", "r")
line_count = 0
for line in file:
if line != "\n":
line_count += 1
file.close()
Label(kariata,bg="white", text=('Total Account:',(line_count)) , fg="green", font="bold").pack()
kariata.after(1000, update) # call update() after 1 second
update() # start the periodic update
Related
Hello i try to write a desktop app with tkinter for typing speed test i search but i cant find my answer is the any way to check the value of user entry in Textbox while app is running ? i need to compare user entry with test text i try to put the function before main loop when i init class but its just check the entry one time and also i try to use window.after()
this is my full code and problem is running last function
def run_test():
random_number = random.randint(1, 5)
test = session.query(data).filter(database.Database.id == random_number).first()
return test
class UserInterFace:
def __init__(self):
customtkinter.set_appearance_mode("dark")
customtkinter.set_default_color_theme("green")
self.window = CTk()
self.window.title("Typing Speed Test Application")
self.window.resizable(False, False)
self.window.config(padx=50, pady=50)
self.window.geometry("1000x700")
self.test = run_test()
self.wrong_entry = 0
self.correct_entry = 0
self.test_running = True
self.start_count = 5
self.start_test_btn = None
self.timer = None
self.start_test_time = None
self.end_test_time = None
self.user_input = []
self.get_ready_label = CTkLabel(master=self.window,
font=timer_font,
text="Get ready Test will be start in :",
text_color="#609EA2")
self.count_down_label = CTkLabel(master=self.window,
font=count_down_font,
text=str(self.start_count),
text_color="#820000")
self.label_test = CTkLabel(master=self.window,
font=my_font2,
text="",
wraplength=900,
)
self.best_score_record = CTkLabel(master=self.window,
font=my_font1,
text_color="#609EA2",
text="")
self.type_area = CTkTextbox(master=self.window,
width=900,
height=200)
self.main()
self.tset_user_text(self.test.text, self.user_input)
self.window.mainloop()
def start_test(self, test):
self.start_test_time = time.time()
self.get_ready_label.grid_forget()
self.count_down_label.grid_forget()
test_id = test.id
test_text = test.text
test_record = test.record
self.label_test.configure(text=test_text)
if test_record == 0:
test_record = "No Record Yet"
else:
test_record = f"Best Record : {test_record}"
self.best_score_record.configure(text=test_record)
self.best_score_record.grid(row=0, column=0)
self.label_test.grid(row=1, column=0, pady=(20, 0))
self.type_area.grid(row=2, column=0, pady=(20, 0))
self.type_area.focus_set()
self.user_input = self.type_area.get("1.0", END)
def main(self):
self.start_test_btn = CTkButton(master=self.window,
text="Start Test",
command=lambda: self.start_time(),
height=100,
width=300,
font=my_font1)
self.start_test_btn.grid(row=0, column=0, padx=(300, 0), pady=(250, 0))
def start_time(self):
if self.start_count >= 0:
self.start_test_btn.grid_forget()
self.get_ready_label.grid(row=0, column=0, pady=(50, 100), padx=(200, 0))
self.count_down_label.grid(row=1, column=0, padx=(200, 0))
self.count_down_label.configure(text=self.start_count)
self.start_count -= 1
self.timer = self.window.after(1000, self.start_time)
else:
self.window.after_cancel(self.timer)
self.start_test(self.test)
def tset_user_text(self, test_text, user_text):
print("test")
test_text_list = list(test_text)
user_text_list = list(user_text)
if len(test_text_list) <= len(user_text_list):
self.test_running = False
self.end_test_time = time.time()
for n in range(len(test_text_list)):
if test_text_list[n] == user_text_list[n]:
self.correct_entry += 1
else:
self.wrong_entry += 1
Okay, so take this with a grain of salt because I can't test this on CustomTkinter, but you should be able to bind an event to your textbox like so:
# call a method called 'on_type' whenever a key is released in the text area
self.type_area.bind('<KeyRelease>', self.on_type)
You can define a callback method to handle this event. Thanks to the binding above, the event parameter is passed to your callback automatically when the event is triggered
def on_type(self, event):
print(event) # do whatever you need to do
FYI: binding to '<KeyRelease>' avoids (some) issues with key repeat caused by held keys
I have been trying to make a Python script that counts how many people are coming and going from your store.
How it is supposed to work:
you have a +1, and a -1 buttons;
when someone comes in, you click +1, and when someone goes away, you do -1.
What is wrong: when I click +1 it changes the counter from 0 to 1, but if I click it again, it doesn't change to 2.
The same thing happens when I do -1.
Here is the code:
import tkinter as tk
import customtkinter as ctk
app = ctk.CTk()
app.title('People Counter')
app.geometry('300x180')
ctk.set_appearance_mode("System")
ctk.set_default_color_theme("blue")
Label = ctk.CTkLabel
StringVar = ctk.StringVar
counter = 0
l1 = tk.Label(app, text=counter)
def pl1():
l1.config(text=counter + 1)
def mi1():
l1.config(text=counter - 1)
p1 = ctk.CTkButton(master=app,text = '+1', command=pl1, height=5 , width=30)
p1.place(relx=0.3, rely=0.5, anchor=tk.CENTER)
m1 = ctk.CTkButton(master=app, text="-1", command=mi1, height=5 , width=30)
m1.place(relx=0.7, rely=0.5, anchor=tk.CENTER)
l1.pack()
app.mainloop()
You only update the text on the label. You don't actually change the value of the counter variable. Try this:
def pl1():
global counter
counter += 1
l1.config(text=counter)
def mi1():
global counter
counter -= 1
l1.config(text=counter)
Another option is to create a simple Counter class with methods add() and sub(). It will help you avoid the use of global variables. I also added a test to prevent the counter get negative numbers.
import tkinter as tk
import customtkinter as ctk
app = ctk.CTk()
app.title('People Counter')
app.geometry('300x180')
ctk.set_appearance_mode("System")
ctk.set_default_color_theme("blue")
Label = ctk.CTkLabel
StringVar = ctk.StringVar
class Counter():
def __init__(self):
self.count = 0
def add(self):
self.count += 1
counter_display.config(text=self.count)
return self.count
def sub(self):
self.count -= 1
if self.count < 0:
self.count = 0
counter_display.config(text=self.count)
return self.count
def __repr__(self):
return str(self.count)
counter = Counter()
counter_display = tk.Label(app, text=counter)
add_one = ctk.CTkButton(
master=app,
text='+1',
command=counter.add,
height=5,
width=30
)
add_one.place(relx=0.3, rely=0.5, anchor=tk.CENTER)
sub_one = ctk.CTkButton(
master=app,
text='-1',
command=counter.sub,
height=5,
width=30
)
sub_one.place(relx=0.7, rely=0.5, anchor=tk.CENTER)
counter_display.pack()
app.mainloop()
Hi i am writing simple typing sped in test in python using tkinter for gui, but i ran into a problem. I want the text in label to change every time the user writes the tenth sentence in entry widget, but when i wrote tenth sentence text in label is changing for example when this word has 5 letters text is changing 5 times. I know why it's hapenning but i don't know how to fix it. thanks.
import tkinter as tk
from tkinter.constants import END
import tkinter.font as font
import random, sys
start = False
# configure tkinter windows
root = tk.Tk()
root.geometry("800x600")
# set window as not resizable
root.resizable(height=False, width=False)
root.title("typing speed test")
# create fonts
myFont = font.Font(size=30)
txtFont = font.Font(size=40)
#this font is needed to entry widget
midFont = font.Font(size=20)
def get_words():
"""
this function open's file and returns
list with content from it
"""
filename = "words.txt"
try:
with open(filename, 'r') as f:
contents = f.read()
#return 10 random words from list
num = random.randrange(0, 990)
contents = contents.split()
return contents[num:num+10]
except FileNotFoundError:
sys.exit("file not founded")
def countdown(count):
"""
this function create timer in tkinter
window
"""
global start
start = True
# change text and font in label
countdown_label['font'] = myFont
countdown_label['text'] = count
if count > 0:
# call countdown again after 1000ms (1s)
root.after(1000, countdown, count-1)
if count <= 10:
# change color of texts
countdown_label["fg"] = "#f00"
if count == 0:
# when count equal 0 disable entry widget
e.config(state='disabled')
#create label
textlabel = tk.Label(root, width=60, height=10, font=midFont, text = "siema")
#add text to label
textlabel.config(text=get_words())
def onValidate(P):
"""
Tkinter validate function
"""
global words
words = P.split()
if P.isalpha() and start == False:
# start counting when user starts
countdown(100)
if len(words) % 10 == 0 :
textlabel.config(text=get_words())
return True
def comapreLists():
"""
This function compare two
lists and return set with
word(s) if it exist in l0
lists
"""
#this list stores words from entry widget
l0 = words
#this list stores words from file
l2 = get_words()
# compare lists
dn = set(l0).intersection(l2)
# return values
return dn
#it's button created only for debug
b = tk.Button(root, text='COMP', command=comapreLists)
#register validate func
vcmd = (root.register(onValidate), '%P')
#create label for timer
countdown_label = tk.Label(root)
#create entry window
e = tk.Entry(validate="key", validatecommand=vcmd,
width=30, font=myFont, state='normal')
#pack elements
countdown_label.pack()
textlabel.pack()
b.pack()
e.place(anchor='center', x=399, y=500)
root.mainloop()
You can use another global variable to store the current number of words entered, then update textLabel only if current number of words not equal to saved one.
last_cnt = 0
def onValidate(P):
"""
Tkinter validate function
"""
global words, last_cnt
if P.isalpha() and start == False:
# start counting when user starts
countdown(100)
words = P.split()
cnt = len(words)
if cnt and (cnt % 10 == 0) and (cnt != last_cnt):
textlabel.config(text=get_words())
last_cnt = cnt
return True
When I run the code below, and press the 'go' button, I get the error:
NameError: name 'be' is not defined
...on the following line in the countdown function:
if be >= 0:
Even if I add global be in the function countdown, I get the same error.
import tkinter as tk
def set1():
global be
if be1 is not '':
be = int(en.get())
def countdown():
global be
if be >= 0:
mins, secs = divmod(be, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
label['text'] = timer
root.after(1000, countdown)
be -= 1
root = tk.Tk()
label = tk.Label(root, text = '00:00', font = 'Helvetica 25')
label.pack()
en = tk.Entry(root)
en.pack()
be1 = en.get()
tk.Button(root, text = 'set', height = 3, width = 20, command = lambda: set1()).pack()
tk.Button(root, text = 'go', height = 3, width = 20, command = lambda: countdown()).pack()
root.mainloop()
Why doesn't global be resolve the problem?
The reason is clear from the error message: you need to define be as a global variable. Note that the global statement does not define the variable, it merely links the local references to that name with an existing global variable. But if it doesn't exist, there is nothing to match it with.
So you should define be as a global variable, like:
be = 0
There are a few other issues and things to improve:
be1 is read from the input only once, when the script starts, not when the user clicks a button. So its value will always remain the empty string. Instead, you should read the input into be1 when the "set" button is clicked, and so the variable be1 can just be a local variable in that set1 function, not global as it is now.
Don't use is not (or is) when comparing a variable with a string literal. So you should have:
if be1 != '':
It is better to already display the updated start-time when the user clicks the "set" button, even before the user clicks "go" -- otherwise they don't see the effect of clicking "set".
Since you already have code for displaying the timer in the countdown function, it would be good to avoid code duplication and make a new function just for doing the displaying.
So taking all that together you would get:
import tkinter as tk
be = 0 # define as global here
def display(): # new function to avoid code repetition
global be
mins, secs = divmod(be, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
label['text'] = timer
def set1():
global be
be1 = en.get() # local variable, reading fresh input value
if be1 != '': # don't use "is not" with a literal
be = int(be1)
display()
def countdown():
global be
if be >= 0:
display()
root.after(1000, countdown)
be -= 1
root = tk.Tk()
label = tk.Label(root, text = '00:00', font = 'Helvetica 25')
label.pack()
en = tk.Entry(root)
en.pack()
tk.Button(root, text = 'set', height = 3, width = 20, command = lambda: set1()).pack()
tk.Button(root, text = 'go', height = 3, width = 20, command = lambda: countdown()).pack()
root.mainloop()
My variable is not changing and I know it's not changing because "1" is printed to the console.
I'm trying to make the label increment when i press the button. However when I press the button, the variable stays at 1.
What am I doing wrong?
I've looked online for an answer but I cannot really find one that I can understand.
num = 0
import tkinter
box = tkinter.Tk()
v = tkinter.StringVar()
labels = tkinter.Label(box, textvariable = v)
labels.pack()
def numberz(num,v):
num += 1
v.set(num)
print(num)
class MainWindow():
box.title("My Stupid Program")
buddon = tkinter.Button(box, text='PRESS ME', command = lambda:numberz(num,v))
buddon.pack()
box.mainloop()
num = 0
import tkinter
box = tkinter.Tk()
v = tkinter.StringVar()
labels = tkinter.Label(box, textvariable = v)
labels.pack()
def numberz(num,v):
num += 1
v.set(num)
print(num)
class MainWindow():
box.title("My Stupid Program")
buddon = tkinter.Button(box, text='PRESS ME', command = lambda:numberz(num,v))
buddon.pack()
box.mainloop()
You are changing the parameter num and not the global variable num
To change the global you need to specifically reference it. Notice how num is not passed in the lambda and now there is a global num in you function.
num = 0
import tkinter
box = tkinter.Tk()
v = tkinter.StringVar()
labels = tkinter.Label(box, textvariable = v)
labels.pack()
def numberz(v):
global num
num += 1
v.set(num)
print(num)
class MainWindow():
box.title("My Stupid Program")
buddon = tkinter.Button(box, text='PRESS ME', command = lambda:numberz(v))
buddon.pack()
box.mainloop()
In any case, using globals should be restricted to very specific cases and not be of general use.