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()
\\
Related
The following code works fine as long as the time in the spinbox does not change. What I want is to do the set the time for a break. The first time it works perfectly but after that if I change the value in the spinbox, the system will check for new value instead of the value which was in the spinbox when the button is clicked.
from tkinter import *
from tkinter import ttk
from datetime import datetime
root = Tk()
root.title("Fusion Calculator")
first_break_time_label = Label(root, text='1st Break:')
first_break_time_label.grid(row=0, column=0)
first_break_time_hour = Spinbox(root, from_=0, to=23, format='%02.0f')
first_break_time_hour.grid(row=0, column=1)
first_break_time_minute = Spinbox(root, from_=0, to=59, format='%02.0f')
first_break_time_minute.grid(row=0, column=2)
first_break_time_second = Spinbox(root, from_=0, to=59, format='%02.0f')
first_break_time_second.grid(row=0, column=3)
loop_active = False # global variable set to false
def check_breaks(): # new loop function that runs set_breaks and reschedules
set_breaks() # for 1 second later.
root.after(1000, check_breaks)
def set_breaks():
check_break = datetime.now().strftime("%H:%M:%S")
first_break_time_value = f'{first_break_time_hour.get()}:{first_break_time_minute.get()}:{first_break_time_second.get()}'
if check_break == first_break_time_value:
popup_first_break = Toplevel(root)
popup_first_break.title('Official Break')
popup_first_break_title_bar = Label(popup_first_break, text='OFFICIAL BREAK', fg='Red')
popup_first_break_title_bar.pack()
else:
pass
global loop_active
if not loop_active: # This will only run when loop_active is false
loop_active = True # Set loop_active to True so it doesn't run again
check_breaks()
set_breaks_button = ttk.Button(root, text='Set', command=set_breaks)
set_breaks_button.grid(row=1, column=3)
root.mainloop()
I tried to bind the button with a mouse click so that it will create an array and get the values into the array. But I am having hard time working with events.
The quick and easy way to do it, would be to create a dictionary that holds each of the breaks values initially set to None, then to populate the dictionary the first time the button is pressed and start the loop at the same time, then have the loop check the dictionary on each iteration for the break times, and set the button command to a function that updates the dictionary when pressed.
For example:
from tkinter import *
from tkinter import ttk
from datetime import datetime
root = Tk()
root.title("Fusion Calculator")
first_break_time_label = Label(root, text='1st Break:')
first_break_time_label.grid(row=0, column=0)
first_break_time_hour = Spinbox(root, from_=0, to=23, format='%02.0f')
first_break_time_hour.grid(row=0, column=1)
first_break_time_minute = Spinbox(root, from_=0, to=59, format='%02.0f')
first_break_time_minute.grid(row=0, column=2)
first_break_time_second = Spinbox(root, from_=0, to=59, format='%02.0f')
first_break_time_second.grid(row=0, column=3)
loop_active = False # global variable set to false
breaks = {
1: None
}
def check_breaks(): # new loop function that runs set_breaks and reschedules
set_breaks() # for 1 second later.
root.after(1000, check_breaks)
def update_break():
first_break_time_value = f'{first_break_time_hour.get()}:{first_break_time_minute.get()}:{first_break_time_second.get()}'
breaks[1] = first_break_time_value
set_breaks()
def set_breaks():
check_break = datetime.now().strftime("%H:%M:%S")
if check_break == breaks[1]:
popup_first_break = Toplevel(root)
popup_first_break.title('Official Break')
popup_first_break_title_bar = Label(popup_first_break, text='OFFICIAL BREAK', fg='Red')
popup_first_break_title_bar.pack()
global loop_active
if not loop_active: # This will only run when loop_active is false
loop_active = True # Set loop_active to True so it doesn't run again
check_breaks()
set_breaks_button = ttk.Button(root, text='Set', command=update_break)
set_breaks_button.grid(row=1, column=3)
root.mainloop()
What might be a better option though would be to start the timed loop at the start of the program that way you can get rid of the loop active variable and extra check function.
Like this:
from tkinter import *
from tkinter import ttk
from datetime import datetime
root = Tk()
root.title("Fusion Calculator")
first_break_time_label = Label(root, text='1st Break:')
first_break_time_label.grid(row=0, column=0)
first_break_time_hour = Spinbox(root, from_=0, to=23, format='%02.0f')
first_break_time_hour.grid(row=0, column=1)
first_break_time_minute = Spinbox(root, from_=0, to=59, format='%02.0f')
first_break_time_minute.grid(row=0, column=2)
first_break_time_second = Spinbox(root, from_=0, to=59, format='%02.0f')
first_break_time_second.grid(row=0, column=3)
breaks = {
1: None
}
def update_break():
first_break_time_value = f'{first_break_time_hour.get()}:{first_break_time_minute.get()}:{first_break_time_second.get()}'
breaks[1] = first_break_time_value
def check_breaks():
check_break = datetime.now().strftime("%H:%M:%S")
if check_break == breaks[1]:
popup_first_break = Toplevel(root)
popup_first_break.title('Official Break')
popup_first_break_title_bar = Label(popup_first_break, text='OFFICIAL BREAK', fg='Red')
popup_first_break_title_bar.pack()
root.after(1000, check_breaks)
check_breaks()
set_breaks_button = ttk.Button(root, text='Set', command=update_break)
set_breaks_button.grid(row=1, column=3)
root.mainloop()
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()
I want to make any btn go to a random spot every 3 milisecounds, and when you click the random button it will do something else like print Hi and stop the button from moving.
Here is the code:
I tried while a == True: but it keeps frezzing when i press the "To make a video" button and just frezzes for a while
import time
import os
import tkinter as tk
import random
from tkinter import *
from tkinter import messagebox
from tkinter import Button
import math
from tkinter import Text
from tkinter import Grid
from tkinter import Place
#from tkinter import place
window = tk.Tk()
window.title("There is no game")
window.geometry("494x300")
numberx = random.randint(1,200)
numbery = random.randint(1,200)
##def clickedrandom():
## a = False
def toplayagame():
print("Hi")
a = True
def tomakeavideo():
T.delete('1.0', END)
T.insert(tk.END, "People who are watching go hit that subscribe button and hit that like button also hit that little bell to turn on notifcations")
T.configure(width = 25, height=6)
while a == True:
numberx = random.randint(1,200)
numbery = random.randint(1,200)
int(numberx)
int(numbery)
time.sleep(0.3)
btn.place(x = numberx, y = numbery)
def pressed():
T.delete('1.0', END)
T.insert(tk.END, "Why are you here?")
btn.place(x=190, y=200)
T.configure(width = 17, height=1)
btn.configure(text = "To play a game", width=12,command=toplayagame)
btn1= Button(window, bd=10,text="To make a video",activebackground='White',activeforeground='Black',bg='Grey',fg='White',height=1,width=15,state=ACTIVE,command=tomakeavideo)
btn1.pack()
btn1.place(x=1,y=200)
T = tk.Text(window, height=1, width=10)
T.pack()
T.insert(tk.END, "Hello user")
btn = Button(window, bd=10,text="Hello",activebackground='Black',activeforeground='White',bg='Grey',fg='White',height=1,width=4,state=ACTIVE,command=pressed)
btn.pack()
btn.place(x=215, y=200)
window.mainloop()
Use the <tkinter widget>.after(<time>, <function>) like this:
import tkinter as tk
import random
playing_game = False
def to_make_video():
global btn1
msg = "People who are watching go hit that subscribe button and"+\
" hit that like button also hit that little bell to turn on"+\
" notifcations"
text_widget.delete("0.0", "end")
text_widget.insert("end", msg)
text_widget.configure(width=25, height=6)
btn1.destroy()
start_game()
def game_won():
# When the button is pressed:
global playing_game
playing_game = False
text_widget.delete("0.0", "end")
text_widget.insert("end", "Why aren't you leaving?")
text_widget.configure(width=23, height=1)
btn.destroy()
def move_button():
global playing_game
# If the game is over stop moving the button
if not playing_game:
return None
# Pick the next random position for the button
numberx = random.randint(1, 200)
numbery = random.randint(1, 200)
btn.place(x=numberx, y=numbery)
# After 500 milliseconds call `move_button` again
# You can change the value to make it faster/slower
root.after(500, move_button)
def start_game():
# Start the game
global playing_game
btn.config(command=game_won)
playing_game = True
# Start the loop that keeps moving it to new random positions
move_button()
def pressed():
global btn1
# Ask the user why they are here
text_widget.delete("0.0", "end")
text_widget.insert("end", "Why are you here?")
text_widget.configure(width=17)
btn.place(x=190, y=200)
btn.configure(text="To play a game", width=12, command=lambda: None)
btn1 = tk.Button(root, bd=10, text="To make a video", bg="grey", fg="white",
activebackground="white", activeforeground="black",
height=1, width=15, command=to_make_video)
btn1.place(x=1, y=200)
# Create a window
root = tk.Tk()
root.geometry("310x250")
text_widget = tk.Text(root, height=1, width=10)
text_widget.pack()
text_widget.insert(tk.END, "Hello user")
btn = tk.Button(root, bd=10, text="Hello", activebackground="black",
activeforeground="white", bg="grey", fg="white", height=1,
width=4, command=pressed)
btn.place(x=215, y=200)
# Run tkinter's mainloop
root.mainloop()
I am trying to modify some code to work for me.
I have a running application with tkinter and I can update both scores (blue and red) when I am pressing the buttons, but I want to find a way how to do this via keypress ? For example to increase the score for the reds when pressing "r" and increase the score for the blue when pressing "b"
Tried different things from google but without any luck.
Could someone have a look and give me some hints?
import tkinter as tk
from time import sleep
window = tk.Tk()
window.configure(bg='black')
window.geometry('1024x600')
window.overrideredirect(True)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLACK = (0, 0, 0)
scoreRed = 0
scoreBlue = 0
global BlueWonBoolean
global RedWonBoolean
BlueWonBoolean = False
RedWonBoolean = False
RedText = tk.StringVar()
BlueText = tk.StringVar()
RedText.set(str(scoreRed))
BlueText.set(str(scoreBlue))
def addBlue():
global scoreBlue
scoreBlue += 1
BlueText.set(str(scoreBlue))
if scoreBlue == 21:
global BlueWonBoolean
BlueWonBoolean = True
print("\nBlue Won!!!\nBLUE | RED\n " + str(scoreBlue) + " : " + str(scoreRed))
global BlueWon
BlueWon = tk.Label(text="Blue Won!!!",
foreground="white",
background="black",
width=10,
height=10)
BlueWon.pack(side=tk.TOP, fill=tk.X)
def addRed():
global scoreRed
scoreRed += 1
RedText.set(str(scoreRed))
if scoreRed == 21:
global RedWonBoolean
RedWonBoolean = True
print("\nRed Won!!!\nRED | BLUE\n" + str(scoreRed) + " : " + str(scoreBlue))
global RedWon
RedWon = tk.Label(text="Red Won!!!",
foreground="white",
background="black",
width=10,
height=10)
RedWon.pack(side=tk.TOP, fill=tk.X)
def resetScore():
global scoreRed
global scoreBlue
global BlueWonBoolean
global RedWonBoolean
scoreRed = 0
scoreBlue = 0
RedText.set(str(scoreRed))
BlueText.set(str(scoreBlue))
BlueLabel.pack(side=tk.LEFT, fill=tk.X)
RedLabel.pack(side=tk.RIGHT, fill=tk.X)
if BlueWonBoolean == True:
BlueWon.destroy()
BlueWonBoolean = False
elif RedWonBoolean == True:
RedWon.destroy()
RedWonBoolean = False
BlueButton = tk.Button(window, text="Blue Point", bg="white", fg="yellow", width=30, height=15, command=addBlue)
RedButton = tk.Button(window, text="Red Point", bg="red", fg="black", width=30, height=15, command=addRed)
ResetButton = tk.Button(window, text="Reset", width=10, height=3, command=resetScore)
BlueLabel.pack(side=tk.LEFT, fill=tk.X)
RedLabel.pack(side=tk.RIGHT, fill=tk.X)
def Quit():
exit()
while True:
try:
BlueLabel = tk.Label(
textvariable=BlueText,
foreground="white",
background="black",
width=10,
height=5
)
RedLabel = tk.Label(
textvariable=RedText,
foreground="white",
background="black",
width=10,
height=5
)
BlueButton = tk.Button(window, text="Blue Point", bg="black", fg="WHITE", width=30, height=15, command=addBlue)
RedButton = tk.Button(window, text="Red Point", bg="black", fg="WHITE", width=30, height=15, command=addRed)
ResetButton = tk.Button(window, text="Reset", bg="black", fg="WHITE", width=10, height=3, command=resetScore)
quitButton = tk.Button(window, text="Quit ", bg="black", fg="WHITE", command=Quit)
# image = tk.PhotoImage(file="cornHole.png")
# imageLabel = tk.Label(image=image)
BlueLabel.pack(side=tk.LEFT, fill=tk.X)
RedLabel.pack(side=tk.RIGHT, fill=tk.X)
BlueButton.pack(side=tk.LEFT, fill=tk.X)
RedButton.pack(side=tk.RIGHT, fill=tk.X)
# imageLabel.pack(side=tk.TOP, fill=tk.X)
quitButton.pack(side=tk.TOP, fill=tk.X)
ResetButton.pack(side=tk.TOP, fill=tk.X)
window.bind("<Escape>", exit)
window.mainloop()
except:
exit()
You can use keybindings to run the function when a key is pressed
window.bind("b", addblue )
Here are a website and a video explaining them further
https://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
https://www.youtube.com/watch?v=GLnNPjL1U2g
Hi #Veleslav Panov and welcome to Stack Overflow! You can use the .bind()method available in tkinter t achieve this task. For example, imagine that you want to update variable on pressing the Enter or the Return key. Then use this:
def function_name(*args):
variable_name +=1
#say the updation to be done here
name_of_window.bind("<Return>", function_name)
Note: Instead of *args, you can use any variable name, the only thing needed is that there should be at least one variable
You can use us .bind() to bind any key to any function, the only requirment is that the function will have some argument, for example 'event'.
def function(event):
#Do something
window.bind("<Return>", function)
This way, every time the button (in this case Enter) is pressed, the function will be called. In your case you would bind 2 buttons, 'r' and 'b', to 2 functions to add score to each of the sides.
Here is a link with some examples:
https://www.geeksforgeeks.org/python-binding-function-in-tkinter/
I'm trying to make a program that will work as an "infomercial" in a separate window.
What i have are two integers (x and y) that both increase at the same time, in this case every 5 seconds. With the increasing values i need a timer displayed at the same time, that can show the elapsed time of how long the program has been running. I want to be albe to start and pause the program
So far i have an infinite while loop running where the values are increased every 5 seconds with time.sleep(5). I have tried implementing a timer in the form of a time.time(), and get it to work with the increments. I have also added buttons but don't work. I'm using tkinter as gui obtion.
How am i supposed to make it work? with threading?
import time
from tkinter import *
import math
usage = 0
yearly = 0
cubik = 0
price = 0
root = Tk()
root.title("Usage of fluid")
root.geometry("300x400")
var = IntVar()
var1 = IntVar()
var2 = StringVar()
var3 = StringVar()
var4 = StringVar()
def update_timeText():
current= time.strftime("%H:%M:%S")
timeText.configure(text=current)
root.after(1000, update_timeText)
def start():
global state
state = True
def pause():
global state
state = False
def exist():
root.destroy()
frame = LabelFrame(root, text="Liter", font=30)
frame.pack(fill = "both", expand="yes")
l = Label(frame, textvariable=var, font=20)
l.pack(pady = 3)
frame2 = LabelFrame(root, text="price from use", font=30)
frame2.pack(fill = "both", expand= "yes")
l2 = Label(frame2, textvariable=var1, font=16)
l2.pack(side = LEFT)
l3 = Label(frame2, text="dollars", font=16)
l3.pack(side=LEFT)
frame3 = LabelFrame(root, text="yearly", font=30)
frame3.pack(fill = "both", expand="yes")
m3 = Label(frame3, textvariable=var2, font=16, wraplength=0)
m3.pack(side=TOP)
l4 = Label(frame3, text="Liter", font=16)
l4.pack(side=TOP)
l5 = Label(frame3, text="m3", font=16)
l5.pack(side=BOTTOM, fill="both")
m4 = Label(frame3, textvariable=var3, font=16, wraplength=0)
m4.pack(side=BOTTOM)
frame4 = LabelFrame(root, text='runtime', font=30)
frame4.pack(fill = "both", expand="yes")
timeText= Label(frame4, text="", font=16)
timeText.pack()
startButton = Button(frame4, text='Start', command=start)
startButton.pack()
pauseButton = Button(frame4, text='Pause', command=pause)
pauseButton.pack()
quitButton = Button(frame4, text='Quit', command=quit)
quitButton.pack()
while True:
var.set(usage)
usage += 300
var1.set(round(price,1))
price+= 10
var2.set(yearly)
var3.set(round(cubik,1))
yearly += 300
cubik += 0.1
time.sleep(5)
update_timeText()
root.update_idletasks()
##update_timeText()
##root.mainloop()