Alternative for while loops in tkinter - python

I am trying to make an alarm application: the alarm should go off at a pre-set time. The piece of code I have works completely fine without tkinter, but with tkinter it doesn't work at all.
In the original piece of code there is a while loop and I've noticed and read that that can't be combined with tkinter. I decided to get rid of the loop, but now the alarm goes off immediately when I enter a time.
I've read about using r.after(time_ms, function()). But I don't know how to implement that properly in my code. I've read that it has to be at the end of the function and before r.mainloop(), but I couldn't get it to work. Can somebody please help me? Thank you very much!
I've read a lot or stackoverflow posts about this, but I am not experienced enough to get it to work with those answers. :(
import tkinter as tk
from datetime import datetime, date
import time
from pygame import mixer
r = tk.Tk()
r.title('Smart Watch')
def alarm_sound():
mixer.init()
mixer.music.load('Wecker-sound.mp3')
def end():
mixer.init()
mixer.music.stop()
def display_output():
hour = entry_hour.get()
int_hour = int(hour)
minute = entry_minute.get()
int_minute = int(minute)
second = entry_second.get()
int_second = int(second)
confirmation_message = ('Alarm has been set for ' + hour + ':' +
minute + ':' + second + '.')
text_label['text'] = confirmation_message
if (time.localtime().tm_hour == hour and
time.localtime().tm_min == entry_minute.get() and
time.localtime().tm_sec == entry_second.get()):
alarm_sound()
mixer.music.play()
message = tk.Label(r, text='What is the alarm message you\'d like to receive when the alarm goes off?',
font=('Roboto-regular', 12), fg='black')
message.pack()
entry_message = tk.Entry(r, width=45)
entry_message.pack()
enter_hour = tk.Label(r, text='Enter the hour for the alarm to go off: ',
font=('Roboto-regular', 12), fg='black')
enter_hour.pack()
entry_hour = tk.Entry(r, width=10)
entry_hour.pack()
enter_minute = tk.Label(r, text='Enter the minute for the alarm to go off: ',
font=('Roboto-regular', 12), fg='black')
enter_minute.pack()
entry_minute = tk.Entry(r, width=10)
entry_minute.pack()
enter_second = tk.Label(r, text='Enter the second for the alarm to go off: ',
font=('Roboto-regular', 12), fg='black')
enter_second.pack()
entry_second = tk.Entry(r, width=10)
entry_second.pack()
text_label = tk.Label(r, font=('Roboto-regular', 12, 'bold'),
fg='tomato')
text_label.pack()
submit_button = tk.Button(r, text='Submit',
fg='black', width=30, height=2, relief='groove',
cursor='hand2', command=display_output)
submit_button.pack()
snooze_button = tk.Button(r, text='Snooze alarm',
fg='black',
width=30, height=2, relief='groove',
cursor='hand2', command=end)
snooze_button.pack()
r.mainloop()
# The original code without tkinter has the while loop like this:
while True:
if time.localtime().tm_hour == hr and time.localtime().tm_min == mn and time.localtime().tm_sec == sc:
print(message)
break
alarm_Sound()
mixer.music.play()

First you should use global variables to keep values from Entry and use them later in function which check time. This function should use after to run its again when there is no time for alarm. It should also skip after() to stop checking time.
def display_output():
global int_hour
global int_minute
global int_second
hour = entry_hour.get()
int_hour = int(hour)
minute = entry_minute.get()
int_minute = int(minute)
second = entry_second.get()
int_second = int(second)
text_label['text'] = 'Alarm has been set for {}:{}:{}.'.format(hour, minute, second)
# start checking time
check_time()
def check_time():
dt = time.localtime()
if (dt.tm_hour == int_hour and dt.tm_min == int_minute and dt.tm_sec == int_second):
alarm_sound()
mixer.music.play()
else:
r.after(1000, check_time) # check it again after 1000ms but only if it doesn't play sound
Code would need other global variables to control if alarm in running when you stop it and when you try to set it again.
import time
from datetime import datetime, date
import tkinter as tk
from pygame import mixer
# --- functions ---
def alarm_sound():
global running_alarm
running_alarm = True
mixer.music.load('Wecker-sound.mp3')
def end():
global running_alarm
if running_alarm:
running_alarm = False
mixer.music.stop()
text_label['text'] = ''
def display_output():
global int_hour
global int_minute
global int_second
hour = entry_hour.get()
int_hour = int(hour)
minute = entry_minute.get()
int_minute = int(minute)
second = entry_second.get()
int_second = int(second)
confirmation_message = ('Alarm has been set for {}:{}:{}.'.format(hour, minute, second))
text_label['text'] = confirmation_message
check_time()
def check_time():
dt = time.localtime()
if (dt.tm_hour == int_hour and dt.tm_min == int_minute and dt.tm_sec == int_second):
checking_time = False # stop l
alarm_sound()
mixer.music.play()
else:
r.after(1000, check_time)
# --- main ---
running_alarm = False # default value at start
mixer.init()
r = tk.Tk()
r.title('Smart Watch')
message = tk.Label(r, text='What is the alarm message you\'d like to receive when the alarm goes off?',
font=('Roboto-regular', 12), fg='black')
message.pack()
entry_message = tk.Entry(r, width=45)
entry_message.pack()
enter_hour = tk.Label(r, text='Enter the hour for the alarm to go off: ',
font=('Roboto-regular', 12), fg='black')
enter_hour.pack()
entry_hour = tk.Entry(r, width=10)
entry_hour.pack()
enter_minute = tk.Label(r, text='Enter the minute for the alarm to go off: ',
font=('Roboto-regular', 12), fg='black')
enter_minute.pack()
entry_minute = tk.Entry(r, width=10)
entry_minute.pack()
enter_second = tk.Label(r, text='Enter the second for the alarm to go off: ',
font=('Roboto-regular', 12), fg='black')
enter_second.pack()
entry_second = tk.Entry(r, width=10)
entry_second.pack()
text_label = tk.Label(r, font=('Roboto-regular', 12, 'bold'), fg='tomato')
text_label.pack()
submit_button = tk.Button(r, text='Submit',
fg='black', width=30, height=2, relief='groove',
cursor='hand2', command=display_output)
submit_button.pack()
snooze_button = tk.Button(r, text='Snooze alarm',
fg='black',
width=30, height=2, relief='groove',
cursor='hand2', command=end)
snooze_button.pack()
r.mainloop()

Instead of the while True: loop, use a function and register a callback for the function every 'specified interval' of time. This is done in the code below:
def wait_for_alarm():
after = r.after(1000, wait_for_alarm) # 1000 refers to 1 second
if time.localtime().tm_hour == hr and time.localtime().tm_min == mn and time.localtime().tm_sec == sc:
print(message)
alarm_Sound()
mixer.music.play()

Related

Tkinter Entry Widget: How to constantly check for activity and delete the field if nothing is typed in a period of time

Trying to write a little program where you type in a Tkinter Entry widget and if you don't type for 5 seconds it deletes everything. The best I can do is have it delete everything on the first key pressed after the five seconds elapses, but I can't figure out how to get it to do it without that extra key press.
import time
from tkinter import *
def click(key):
global click_before_last_click, last_click
# print(key.char)
click_before_last_click = last_click
last_click = time.time()
# print(click_before_last_click)
# print(last_click)
delete_shit()
def disappearing_text_start():
global click_before_last_click, last_click
click_before_last_click = time.time()
last_click = time.time()
entry.delete(1.0, END)
entry.bind("<Key>", click)
def disappearing_text_end():
text_file = open("result.txt", "w")
text_file.write(entry.get(1.0, END))
text_file.close()
entry.delete(1.0, END)
def delete_shit():
if last_click > click_before_last_click + 5:
print("TOO LONG")
entry.delete(1.0, END)
if __name__ == "__main__":
click_before_last_click = time.time()
last_click = time.time()
window = Tk()
window.title("Disappearing Text")
window.config(padx=50, pady=20, bg="#D3D3D3")
title_label = Label(text="Disappearing Text App", fg="black", bg="#D3D3D3", font=("Courier", 24))
title_label.grid(column=1, row=0, columnspan=2)
label = Label(text="Click start to begin, and end to save your text. "
"If you stop typing for 5 seconds, you lose everything.",
bg="#D3D3D3", font=("Courier", 14))
label.grid(column=1, row=1, columnspan=2)
entry = Text(width=100, height=30)
entry.grid(column=1, columnspan=2, row=3)
start_button = Button(text="Start", command=disappearing_text_start)
start_button.grid(column=1, row=4, pady=20)
end_button = Button(text="Save", command=disappearing_text_end)
end_button.grid(column=2, row=4, pady=20)
window.mainloop()
You can use after to delete the characters after the time interval. Each time the user presses a key, delete the old scheduled function and then reschedule it.
Also, FWIW, you've used an index of 1.0 which is invalid. Tkinter will accept it, but an index is a string rather than a floating point number.
Let's start by writing a function that will schedule the text to be deleted in 5 seconds. It will also cancel any pending job, effectively resetting the timer to zero. It needs to accept an event parameter since it will be called from a key binding.
after_id = None
def schedule_delete(event=None):
global after_id
if after_id:
window.after_cancel(after_id)
after_id = window.after(5000, delete_shit)
Next, arrange for this to be called when the user clicks the "start" button. disappearing_text_start might look something like this:
def disappearing_text_start():
schedule_delete()
entry.delete("1.0", END)
You can then call this bind command once in the main body of of your program to have reschedule_delete called on every keypress:
entry.bind("<Any-KeyPress>", reschedule_delete)
Finally, we need to cancel any pending job when the user clicks the "stop" button:
def disappearing_text_end():
global after_id
if after_id:
window.after_cancel(after_id)
after_id = None
... the rest of your code here ...
Here's a complete working example:
from tkinter import *
def click(key):
schedule_delete()
def disappearing_text_start():
schedule_delete()
entry.delete("1.0", END)
def schedule_delete(event=None):
global after_id
if after_id:
window.after_cancel(after_id)
after_id = window.after(5000, delete_shit)
def disappearing_text_end():
global after_id
if after_id:
window.after_cancel(after_id)
after_id = None
text_file = open("result.txt", "w")
text_file.write(entry.get(1.0, END))
text_file.close()
entry.delete("1.0", END)
def delete_shit():
entry.delete("1.0", END)
if __name__ == "__main__":
# this is used to keep track of the scheduled function call
after_id = None
window = Tk()
window.title("Disappearing Text")
window.config(padx=50, pady=20, bg="#D3D3D3")
title_label = Label(text="Disappearing Text App", fg="black", bg="#D3D3D3", font=("Courier", 24))
title_label.grid(column=1, row=0, columnspan=2)
label = Label(text="Click start to begin, and end to save your text. "
"If you stop typing for 5 seconds, you lose everything.",
bg="#D3D3D3", font=("Courier", 14))
label.grid(column=1, row=1, columnspan=2)
entry = Text(width=100, height=30)
entry.grid(column=1, columnspan=2, row=3)
start_button = Button(text="Start", command=disappearing_text_start)
start_button.grid(column=1, row=4, pady=20)
end_button = Button(text="Save", command=disappearing_text_end)
end_button.grid(column=2, row=4, pady=20)
entry.bind("<Any-KeyPress>", schedule_delete)
window.mainloop()

Can't stop timer in python (after and after_cancel)

I am trying to create a timer in a tkinter GUI that initiates on a start button, and stops on a stop button. I am using .after to loop the timer, but I can't correctly integrate .after_cancel. Any advice would be greatly appreciated.
#import python modules
import time
import math
from tkinter import *
#Create a root window to work in
root = Tk()
root.title("CNT Synthesis Controller") #title of file
#Create global variables to be stored
global var_status
global current_time
global start_time
current_time = 0
#Create Labels
myLabel_Status_T = Label(root, text="Total time elapsed (hrs:min:sec):")
myLabel_Timer = Label(root, text="00:00:00")
#Locate labels
myLabel_Status_T.grid(row=0, column=0)
myLabel_Timer.grid(row=1, column=0)
#Start button function
def Click_Start():
#disable Start Button to prevent re-start
myButton_Start.config(state=DISABLED)
#initiate time = 0 and start timer
start_time = time.time()
global Timer_continue
Timer_continue = True
#Timer function
def Timer():
#determine the amount of time passed since start_time measured
current_time = int(time.time()-start_time)
hour = math.floor(current_time/3600)
minute = math.floor((current_time/60)-(hour*60))
second = math.floor(current_time-(hour*3600)-(minute*60))
#shows time as 00:00:00, i.e. adding in the zeroes where needed
if hour<10:
hour=str("0"+str(hour))
else:
hour=str(hour)
if minute<10:
minute=str("0"+str(minute))
else:
minute=str(minute)
if second<10:
second=str("0"+str(second))
else:
second=str(second)
#print the time to the label myLabel_Timer
myLabel_Timer.config(text= hour + ":" + minute + ":" + second)
#after 1000 ms repeat the Timer function
#while (myButton_Stop['state'] != tk.DISABLED):
#Timer_Object=myLabel_Timer.after(1000,Timer)
if Timer_continue == True:
root.after(1000,Timer)
if Timer_continue == False:
root.after_cancel(Timer)
Timer()
#Stop button function
def Click_Stop():
Timer_continue = False
#disable Stop Button to prevent re-use until program is reset
myButton_Stop.config(state=DISABLED)
#Create Buttons
myButton_Start = Button(root,text="Start CNT Synthesis", padx=40, pady=20, fg="white", bg="green", command=Click_Start)
myButton_Stop = Button(root,text="Stop CNT Synthesis", padx=40, pady=20, fg="white", bg="red", command=Click_Stop)
#Locate buttons
myButton_Start.grid(row=2, column=0)
myButton_Stop.grid(row=2, column=1)
root.mainloop()
####---------------------------------------------------------------------Required added text to make the question 'long enough'--------------------------------------------------------------------------------------------##########
You need to save the ID returned by .after() and use it in .after_cancel() to stop the timer inside Click_Stop() function:
#import python modules
import time
from tkinter import *
#Create a root window to work in
root = Tk()
root.title("CNT Synthesis Controller") #title of file
#Create Labels
myLabel_Status_T = Label(root, text="Total time elapsed (hrs:min:sec):")
myLabel_Timer = Label(root, text="00:00:00")
#Locate labels
myLabel_Status_T.grid(row=0, column=0)
myLabel_Timer.grid(row=1, column=0)
Timer_id = None # used to store the ID returned by .after()
#Start button function
def Click_Start():
#disable Start Button to prevent re-start
myButton_Start.config(state=DISABLED)
#enable Stop Button
myButton_Stop.config(state=NORMAL)
#save the start timer
start_time = time.time()
#Timer function
def Timer():
global Timer_id
#determine the amount of time passed since start_time measured
elapsed = int(time.time()-start_time)
minutes, seconds = divmod(elapsed, 60)
hours, minutes = divmod(minutes, 60)
myLabel_Timer.config(text=f"{hours:02}:{minutes:02}:{seconds:02}")
#after 1000 ms repeat the Timer function
Timer_id = root.after(1000,Timer) # save the after ID
Timer()
#Stop button function
def Click_Stop():
if Timer_id:
root.after_cancel(Timer_id) # cancel the scheduled task
#disable Stop Button to prevent re-use until program is reset
myButton_Stop.config(state=DISABLED)
#enable Start Button
myButton_Start.config(state=NORMAL)
#Create Buttons
myButton_Start = Button(root,text="Start CNT Synthesis", padx=40, pady=20,
fg="white", bg="green", command=Click_Start)
myButton_Stop = Button(root,text="Stop CNT Synthesis", padx=40, pady=20,
fg="white", bg="red", command=Click_Stop, state=DISABLED) # disable stop button initially
#Locate buttons
myButton_Start.grid(row=2, column=0)
myButton_Stop.grid(row=2, column=1)
root.mainloop()
Miss the global statement:
def Click_Stop():
global Timer_continue
Timer_continue = False

How to overwrite a Timer in Python

I have 2 buttons(rotate and reverse). When either button is ON the other is deactivated as both cannot be on at the same time. When On button is turned OFF, it gives the disabled button 10 seconds before back to Normal.
My question is How can I stop the 10sec timer if I was to hit ON(same button turned off) before the 10 second timer. Example, If I turn ON rotate then OFF(this starts 10 second timer for Reverse) but if decide to turn rotate ON again my timer to reverse button is still counting. How can I stop the timer, so that if I turn OFF again it can start new 10sec?
\\
from tkinter import *
from tkinter import font
from threading import Timer
from time import sleep
reverse_motor = True
rotate_motor = True
def hp30():
global rotate_motor
# Turn ON 30hp Motor
if rotate_motor:
rotate_motor = False
motor30hp.config(activebackground=motor30hp.cget('background'))
reverseButton["state"] = DISABLED
motor30hp["text"] = "ON"
motor30hp["bg"] = "green"
print("30hp Motor ON")
motor30hp.config(activebackground=motor30hp.cget('background'))
else:
# Turn OFF 30hp Motor
rotate_motor = True
motor30hp["text"] = "OFF"
motor30hp["bg"] = "red"
print("30hp Motor OFF")
motor30hp.config(activebackground=motor30hp.cget('background'))
tim01 = Timer(10, normal_reverse)
tim01.start()
print("Reverse 10 sec Timer On")
def reverse():
global reverse_motor
if reverse_motor:
reverse_motor = False
motor30hp["state"] = DISABLED
print("Rotate Disabled")
reverseButton.config(activebackground=reverseButton.cget('background'))
print("Reverse Motor ON")
reverseButton["text"] = "ON"
reverseButton["bg"] = "green"
else:
reverse_motor = True
reverseButton["text"] = "OFF"
reverseButton["bg"] = "red"
reverseButton.config(activebackground=reverseButton.cget('background'))
print("Reverse Motor OFF")
timer = Timer(10, normal_hp30)
timer.start()
print("Rotate 10 sec Timer On")
def normal_hp30():
motor30hp.config(state='normal')
print("Rotate Enabled")
def normal_reverse():
reverseButton.config(state='normal')
print("Reverse Enabled")
root = Tk()
root.title("SOTS Remote")
root.geometry('400x150+0+0')
root.configure(background="black")
myFont = font.Font(family='Times', size=30, weight='bold')
#-------------------------------lABELS--------------------------------------------------------
root.label2 = Label(root, text="Rotate", font=myFont, fg="white", bg="black")
root.label2.grid(row=0, column=1, sticky="W", padx=25, pady=2)
root.label3 = Label(root, text="Reverse", font=myFont, fg="white", bg="black", padx=30)
root.label3.grid(row=0, column=0, sticky="NW", pady=2)
#----------------------------------------buttons--------------------------------------------------
reverseButton = Button(root, text="OFF", font=myFont, height=1, width=7, bg='dodgerblue',
command=reverse, relief=RIDGE,bd=5)
reverseButton.grid(row=1, column=0, sticky="NW")
reverseButton.config(activebackground=reverseButton.cget('background'))
motor30hp = Button(root, text="OFF", bg='red', relief=RIDGE, bd=5, font=myFont,
command=hp30, height=1, width=7)
motor30hp.grid(row=1, column=1, sticky="W")
motor30hp.config(activebackground=motor30hp.cget('background'))
root.mainloop()
\\

Tkinter - For Loop too early

I have a code for a "Magic Mirror" where I want to display clock, title and news (in Japanese).
I have a whole code that works fine with a news code inside it - In Tkinter loop - news code takes whole messages with json, hide everything except of title, put them to the list and shows loop through it to show messages one by one. It works well in terminal, but I have a struggles to put it into Tkinter window loop - It loops through it and shows only the last news subject - I would like them all, one every 10 seconds, or so... Is there a way to do it please? I will be happy for every answer, thanks.
Here is THE Code
import tkinter as tk
from tkinter import *
startupscreen = tk.Tk()
startupscreen.title('Magic Mirror: Python Mod')
welcometext = tk.Label(startupscreen, font = ('caviar dreams', 40), bg='black', fg='white')
startupscreen.configure(background='black')
startupscreen.overrideredirect(True)
welcometext.config(text='Mirror: Vuoristo Mod')
welcometext.pack(side=LEFT, padx= 120, pady=80)
# Gets the requested values of the height and widht.
windowWidth = startupscreen.winfo_reqwidth()
windowHeight = startupscreen.winfo_reqheight()
# Gets both half the screen width/height and window width/height
positionRight = int(startupscreen.winfo_screenwidth()/3 - windowWidth/2)
positionDown = int(startupscreen.winfo_screenheight()/2 - windowHeight/2)
# Positions the window in the center of the page.
startupscreen.geometry("+{}+{}".format(positionRight, positionDown))
startupscreen.update()
import time
from newsapi import NewsApiClient
import os
import feedparser
import json
from time import sleep
decrypt = list()
global iteration
global timecount
global repull
global sleep
iteration = 0
timecount = 0
repull = 0
sleep = 0
while True:
def tick(time1=''):
time2 = time.strftime("%H")
if time2 != time1:
time1 = time2
clock_frame.config(text=time2)
clock_frame.after(200, tick)
def tickk(time3=''):
time4 = time.strftime(":%M:%S")
if time4 != time3:
time3 = time4
clock_frame2.config(text=time4)
clock_frame2.after(200, tickk)
#This function waits for a certain amount of 'tocks' and then initiates 'newsheader' -function
def tock():
global timecount
global repull
global sleep
global decrypt
newstitle.after(200, tock)
if timecount < 20:
timecount +=1
else:
timecount = 0
newsheader()
if repull < 200:
repull +=1
if sleep < 800:
sleep+=1
else:
sleep = 0
motiondetector()
#This function iterates over the news headlines. Iteration is the news number, 'itemlist' brings out only the title.
def newsheader():
url = 'https://news.google.com/rss?hl=ja&gl=JP&ceid=JP:ja'
d = feedparser.parse(url)
news = list()
for i, entry in enumerate(d.entries, 1):
p = entry.published_parsed
sortkey = "%04d%02d%02d%02d%02d%02d" % (p.tm_year, p.tm_mon, p.tm_mday, p.tm_hour, p.tm_min, p.tm_sec)
tmp = {
"title": entry.title,
#"link": entry.link,
"sortkey": sortkey
}
news.append(tmp)
news = sorted(news, key=lambda x: x['sortkey'])
myDict = {}
# HERE IS THE PROBLEM, I HAVE LIKE 30 news IN `frequency`, BUT IT SHOWS ONLY LAST ONE
for d in news:
c = d['title']
myDict[c] = myDict.get(c,0)+1
frequency = myDict.keys()
frequency = list(frequency)
for x in range(len(frequency)):
source.config(text=str(frequency[x]))
x += 1
root = tk.Tk()
root.title('Mirror')
lab = Label(root, text=" 日本", font = ('', 40), bg='black', fg='white')
lab.pack(anchor=SW, fill=X, padx=45)
masterclock = tk.Label(root)
masterclock.pack(anchor=NW, fill=X, padx=45)
masterclock.configure(background='black')
clock_frame = tk.Label(root, font = ('caviar dreams', 130), bg='black', fg='white')
clock_frame.pack(in_=masterclock, side=LEFT)
clock_frame2 = tk.Label(root, font = ('caviar dreams', 70), bg='black', fg='white')
clock_frame2.pack(in_=masterclock, side=LEFT, anchor = N, ipady=15)
newstitle = tk.Label(root, font = ('caviar dreams', 30), bg='black', fg='white')
newstitle.pack(side=BOTTOM, anchor=W, fill=X)
source = tk.Label(root, font = ('caviar dreams', 20), bg='black', fg='white')
source.pack(side=BOTTOM, anchor=W, fill=X)
newsheader()
tick()
tickk()
tock()
root.attributes("-fullscreen", True)
root.configure(background='black')
startupscreen.destroy()
root.mainloop()
This code use function display_next_item to get next element from list frequency and put in Label. And it use after() to do it again after 1 second. You can set 10 seconds but for test I use smaller value.
For tests I also had to removed fullscreen and newsapi (which I don't have installed)
import tkinter as tk
from tkinter import *
startupscreen = tk.Tk()
startupscreen.title('Magic Mirror: Python Mod')
welcometext = tk.Label(startupscreen, font = ('caviar dreams', 40), bg='black', fg='white')
startupscreen.configure(background='black')
startupscreen.overrideredirect(True)
welcometext.config(text='Mirror: Vuoristo Mod')
welcometext.pack(side=LEFT, padx= 120, pady=80)
# Gets the requested values of the height and widht.
windowWidth = startupscreen.winfo_reqwidth()
windowHeight = startupscreen.winfo_reqheight()
# Gets both half the screen width/height and window width/height
positionRight = int(startupscreen.winfo_screenwidth()/3 - windowWidth/2)
positionDown = int(startupscreen.winfo_screenheight()/2 - windowHeight/2)
# Positions the window in the center of the page.
startupscreen.geometry("+{}+{}".format(positionRight, positionDown))
startupscreen.update()
import time
#from newsapi import NewsApiClient
import os
import feedparser
import json
from time import sleep
decrypt = list()
global iteration
global timecount
global repull
global sleep
iteration = 0
timecount = 0
repull = 0
sleep = 0
while True:
def tick(time1=''):
time2 = time.strftime("%H")
if time2 != time1:
time1 = time2
clock_frame.config(text=time2)
clock_frame.after(200, tick)
def tickk(time3=''):
time4 = time.strftime(":%M:%S")
if time4 != time3:
time3 = time4
clock_frame2.config(text=time4)
clock_frame2.after(200, tickk)
#This function waits for a certain amount of 'tocks' and then initiates 'newsheader' -function
def tock():
global timecount
global repull
global sleep
global decrypt
newstitle.after(200, tock)
if timecount < 20:
timecount +=1
else:
timecount = 0
newsheader()
if repull < 200:
repull +=1
if sleep < 800:
sleep+=1
else:
sleep = 0
motiondetector()
#This function iterates over the news headlines. Iteration is the news number, 'itemlist' brings out only the title.
def newsheader():
url = 'https://news.google.com/rss?hl=ja&gl=JP&ceid=JP:ja'
d = feedparser.parse(url)
news = list()
for i, entry in enumerate(d.entries, 1):
p = entry.published_parsed
sortkey = "%04d%02d%02d%02d%02d%02d" % (p.tm_year, p.tm_mon, p.tm_mday, p.tm_hour, p.tm_min, p.tm_sec)
tmp = {
"title": entry.title,
#"link": entry.link,
"sortkey": sortkey
}
news.append(tmp)
news = sorted(news, key=lambda x: x['sortkey'])
myDict = {}
for d in news:
c = d['title']
myDict[c] = myDict.get(c,0)+1
global frequency
frequency = list(myDict.keys())
def display_next_item():
global frequency
global next_index
next_index += 1
if next_index >= len(frequency):
next_index = 0
source.config(text=str(frequency[next_index]))
root.after(1000, display_next_item)
frequency = [] # value at start
next_index = 0 # value at start
root = tk.Tk()
root.title('Mirror')
lab = Label(root, text=" 日本", font = ('', 40), bg='black', fg='white')
lab.pack(anchor=SW, fill=X, padx=45)
masterclock = tk.Label(root)
masterclock.pack(anchor=NW, fill=X, padx=45)
masterclock.configure(background='black')
clock_frame = tk.Label(root, font = ('caviar dreams', 130), bg='black', fg='white')
clock_frame.pack(in_=masterclock, side=LEFT)
clock_frame2 = tk.Label(root, font = ('caviar dreams', 70), bg='black', fg='white')
clock_frame2.pack(in_=masterclock, side=LEFT, anchor = N, ipady=15)
newstitle = tk.Label(root, font = ('caviar dreams', 30), bg='black', fg='white')
newstitle.pack(side=BOTTOM, anchor=W, fill=X)
source = tk.Label(root, font = ('caviar dreams', 20), bg='black', fg='white')
source.pack(side=BOTTOM, anchor=W, fill=X)
newsheader()
tick()
tickk()
tock()
display_next_item() # <- start displaying
#root.attributes("-fullscreen", True)
root.configure(background='black')
startupscreen.destroy()
root.mainloop()
You need to use threading. And you can create a Repeating class or a Background class to perform your news reading every 10 seconds like this.

python GUI countdown timer (don't use classes)

i have just one problem in my source code, lbl_time will not change, all thing running well except this.
I could only use function in my program, if someone can help me in this functional program, please do it.
import tkinter as tk
from datetime import timedelta
import winsound
set time is a function that for counting down time, i use timedelta for building a time object to simple operation
def main():
def set_time(hours:int=0, minutes:int=0, seconds:int=0):
end = timedelta(hours=hours, minutes=minutes, seconds=seconds)
one_second = timedelta(seconds=1)
result = end - one_second
new_time = seconds_to_hms(result.seconds)
if result.seconds is 0:
while True:
try:
winsound.PlaySound("Ringtones\\1.cookie clock.wav", winsound.SND_FILENAME)
except KeyboardInterrupt:
break
else:
hours, minutes, seconds = new_time.get('hours'), new_time.get('minutes'), new_time.get('seconds')
time.set(str(hours)+':'+str(minutes)+':'+str(seconds))
root.update()
root.after(1000, lambda : set_time(hours, minutes, seconds))
def seconds_to_hms(seconds:int) -> dict:
hours, minutes, seconds = 0, 0, seconds
if seconds >= 3600:
hours = seconds//3600
seconds = seconds - hours*3600
if seconds >= 60:
minutes = seconds//60
seconds = seconds - minutes*60
result = {'hours': hours, 'minutes': minutes, 'seconds': seconds}
return result
def quit(*args):
root.destroy()
root = tk.Tk()
root.title(string='Timer')
time = tk.StringVar()
root.configure(background='black')
logo = tk.PhotoImage(file='Logo.png')
lbl_logo = tk.Label(root, image=logo, bg='black').pack(side='right')
lbl_timer = tk.Label(root, padx=10, text="Timer", fg='white', bg='black', font='Times 24', anchor='center').pack()
lbl_time = tk.Label(root, text=time, font="Times 38", fg='white', bg='black').pack()
btn_start = tk.Button(root, text='start', bg='gray', fg='black', command=lambda : set_time()).pack()
root.bind('x', quit)
root.after(1000, lambda : set_time(0,0, 3))
root.mainloop()
if __name__ == '__main__':
main()
Took some time to understand your question, but I might have solved your problem.
Fundamentally you ought to have used textvariable rather than text as an argument in your lbl_time declaration.
If your while loop is executed, it might result in an infinite loop, you might want to have an increment if the code branches there.
Do check out the following, you might want to uncomment some of the lines, hopefully it does solve your problem:
import tkinter as tk
from datetime import timedelta
import winsound
def main():
def set_time(hours:int=0, minutes:int=0, seconds:int=0):
end = timedelta(hours=hours, minutes=minutes, seconds=seconds)
one_second = timedelta(seconds=1)
result = end - one_second
new_time = seconds_to_hms(result.seconds)
if result.seconds is 0:
while True:
try:
winsound.PlaySound("Ringtones\\1.cookie clock.wav", winsound.SND_FILENAME)
except KeyboardInterrupt:
break
else:
hours, minutes, seconds = new_time.get('hours'), new_time.get('minutes'), new_time.get('seconds')
time.set(str(hours)+':'+str(minutes)+':'+str(seconds))
root.update()
root.after(1000, lambda : set_time(hours, minutes, seconds))
def seconds_to_hms(seconds:int) -> dict:
hours, minutes, seconds = 0, 0, seconds
if seconds >= 3600:
hours = seconds//3600
seconds = seconds - hours*3600
if seconds >= 60:
minutes = seconds//60
seconds = seconds - minutes*60
result = {'hours': hours, 'minutes': minutes, 'seconds': seconds}
return result
def quit(*args):
root.destroy()
root = tk.Tk()
root.title(string='Timer')
time = tk.StringVar()
root.configure(background='black')
# logo = tk.PhotoImage(file='Logo.png')
# lbl_logo = tk.Label(root, image=logo, bg='black').pack(side='right')
lbl_timer = tk.Label(root, padx=10, text="Timer", fg='white', bg='black', font='Times 24', anchor='center').pack()
lbl_time = tk.Label(root, textvariable=time, font="Times 38", fg='white', bg='black').pack() #changed text to textvariable
btn_start = tk.Button(root, text='start', bg='gray', fg='black', command=lambda :set_time(0,0,3700)).pack()
root.bind('x', quit)
#root.after(1000, lambda : set_time(0,0, 3))
root.mainloop()
if __name__ == '__main__':
main()

Categories

Resources