Off Button Not working in python. I have a code in python in which I'm trying to get the off button to turn a function off while the function on is running. as on runs it prints out hello every 5 seconds and I want the off button to stop this. Every time I press the off button it freezes while hello is still being played or python crashes. How can I fix this?.
Here is the code I have so far:
from tkinter import *
import threading
root = Tk()
def on():
threading.Timer(5.0, on).start()
print("hello")
def off():
exit()
buttonstart = Button(root, text="on", command=on)
button = Button(root, text="off", command=off)
buttonstart.pack()
button.pack()
root.mainloop()
You can use cancel() to cancel the Timer():
timer_task = None
def on():
global timer_task
buttonstart.config(state=DISABLED)
timer_task = threading.Timer(5.0, on)
timer_task.start()
print('hello')
def off():
global timer_task
if timer_task:
timer_task.cancel()
buttonstart.config(state=NORMAL)
timer_task = None
Related
I'm writing a program in tkinter using Progressbar. But there is a problem when I added stop function it doesn't work. When I press "stop" button nothing happens, it should stop loading progressbar. I use Python version 3.8. The code below:
from tkinter import *
from tkinter import ttk
import time
root = Tk()
def run():
pb['maximum']=100
for i in range(101):
time.sleep(0.05)
pb['value']=i
pb.update()
def stop():
pb.stop()
runbutt = Button(root,text="Runprogr",command=run)
runbutt.pack()
stopbutt = Button(root,text="Stopbut",command=stop)
stopbutt.pack()
pb = ttk.Progressbar(root,length=300,orient="horizontal")
pb.pack()
root.geometry("300x300")
root.mainloop()
The cause is that pb.stop couldn't stop the function in run.it will also increase by itself.
You could use .after(ms, callback) to add the value(then you no longer need to use time.sleep()).
If you want to stop it,use .after_cancel():
from tkinter import *
from tkinter import ttk
import time
root = Tk()
root.add_value = None
def run():
def add():
if pb['value'] >= 100:
return
pb['value'] += 1
root.add_value = root.after(50, add)
if root.add_value: # to prevent increasing the speed when user pressed "Runprogr" many times.
return
root.add_value = root.after(50, add)
def stop():
if not root.add_value: # to prevent raising Exception when user pressed "Stopbut" button many times.
return
root.after_cancel(root.add_value)
root.add_value = None
runbutt = Button(root, text="Runprogr", command=run)
runbutt.pack()
stopbutt = Button(root, text="Stopbut", command=stop)
stopbutt.pack()
pb = ttk.Progressbar(root, length=300, orient="horizontal")
pb.pack()
root.geometry("300x300")
root.mainloop()
I have created a GUI with a "stop" button. When the GUI is ran, another module is called that contains a while loop for a background function. The stop button would be used to pass a variable to the loop to stop it. However, when the module containing the loop is called the GUI freezes. I have considered using the library "threading" but cannot find any tkinter specific content. Any advice or small example of how you would create the code would help a lot.
Here is a basic GUI with 2 buttons that can start and stop a thread which increments a variable count.
I let you try it :
import tkinter as tk
import threading
import time
class GUI(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title("test")
self.button_start = tk.Button(self, text="Start", command=self.start_thread)
self.button_start.pack()
self.button_stop = tk.Button(self, text="Stop", command=self.stop_thread)
self.button_stop.pack()
self.count = 0
self.continue_thread = True
def start_thread(self):
self.count = 0
self.continue_thread = True
self.t1 = threading.Thread(target = self.counter)
self.t1.daemon = True # With this parameter, the thread functions stops when you stop the main program
self.t1.start()
def stop_thread(self):
self.continue_thread = False
self.t1.join()
def counter (self):
while self.continue_thread:
print("i =", self.count)
self.count += 1
time.sleep(1)
if __name__ == "__main__":
app = GUI()
app.mainloop()
This is just a sample program to illustrate how to kill a running thread.
import threading
import time
def run():
while True:
print('thread running')
global stop_threads
if stop_threads:
break
if __name__=="__main__":
stop_threads = False
t1 = threading.Thread(target = run) ##background loop
t1.start()
time.sleep(1)
#while clicking on the button in GUI kill the thread like this
stop_threads = True
t1.join()
print('thread killed')
I have created a Python GUI with tKinter in my simple example I have a button that triggers a simple loop that increments a counter. I have succesfully threaded the counter so my GUI won't freeze, however I am having issues with getting it to stop counting. Here is my code:
# threading_example.py
import threading
from threading import Event
import time
from tkinter import Tk, Button
root = Tk()
class Control(object):
def __init__(self):
self.my_thread = None
self.stopThread = False
def just_wait(self):
while not self.stopThread:
for i in range(10000):
time.sleep(1)
print(i)
def button_callback(self):
self.my_thread = threading.Thread(target=self.just_wait)
self.my_thread.start()
def button_callbackStop(self):
self.stopThread = True
self.my_thread.join()
self.my_thread = None
control = Control()
button = Button(root, text='Run long thread.', command=control.button_callback)
button.pack()
button2 = Button(root, text='stop long thread.', command=control.button_callbackStop)
button2.pack()
root.mainloop()
How can I safely make the counter stop incrementing and gracefully close the thread?
You have to check for self.stopThread inside the for loop
So you want a for loop AND a while loop to run in parallel? Well they can't. As you have them, the for loop is running and won't pay attention to the while loop condition.
You need to make only a single loop. If you want your thread to auto terminate after 10000 cycles, you could do it like this:
def just_wait(self):
for i in range(10000):
if self.stopThread:
break # early termination
time.sleep(1)
print(i)
I am totally new in python GUI and Tkinter. Now i want an entry field where i can change the value or time of self.hide when i will execute this code. that means self.hide value will change from Entry field. In this code this value is statically set to 1 minute. need help from experts.
import Tkinter as Tk
import time
import tkMessageBox
class Window:
def __init__(self):
self.root = None
self.hide = 1 #minutes
self.show = 3 #seconds
def close(self):
self.root.destroy()
return
def new(self):
self.root = Tk.Tk()
self.root.overrideredirect(True)
self.root.geometry("{0}x{1}+0+0".format(self.root.winfo_screenwidth(), self.root.winfo_screenheight()))
self.root.configure(bg='black')
Tk.Label(self.root, text='Hello', fg='white', bg='black', font=('Helvetica', 30)).place(anchor='center', relx=0.5, rely=0.5)
#tkMessageBox.showinfo("Notification", "Your time is up. Time to do next job. . .")
Tk.Button(text = 'Close', command = self.close).pack()
self.root.after(self.show*1000, self.pp)
def pp(self):
if self.root:
self.root.destroy()
time.sleep(self.hide*60)
self.new()
self.root.mainloop()
return
Window().pp()
Try This. It may help you.
from Tkinter import *
import time
root = Tk()
def close():
root.destroy()
def show():
root.deiconify()
button.config(text = 'Close', command = close)
root.after(1000, hide)
def hide():
root.withdraw()
time_to_sleep = set_time_to_sleep.get()
time_to_sleep = float(time_to_sleep)
#print time_to_sleep
time.sleep(time_to_sleep)
show()
set_time_to_sleep = Entry(root)
set_time_to_sleep.pack(side=LEFT)
button = Button(text = 'Set Time', command = hide)
button.pack()
root.mainloop()
To summarise:
Instead of using the sleep function, use the after function. This will not freeze the GUI.
Set the "wait" time of the after function self.Entry.get(). This will collect the info you have put into the Entry.
For more info, look at these links. People smarter than myself give a very clear explication on how to use the functions.
Tkinter, executing functions over time
tkinter: how to use after method
I am new to python and i am trying to make a countdown timer on a button click. But i would like this countdown timer to start its countdown and place the current countdown value in the text area. Also i need the rest of the application to not sleep while this countdown is running. So far it will output the countdown in the console but will freeze the rest of the application. Can someone point me in the right direction?
from Tkinter import *
import time
import threading
import thread
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.getvalue = Button(frame, text="Get the Text Area", command=self.thevalue)
self.getvalue.pack(side=LEFT)
self.text_area = Entry()
self.text_area.pack(side=RIGHT)
def thevalue(self):
print "In the value"
try:
t = threading.Thread(target=self.print_time("I am in print_time"))
t.daemon = True
t.start()
except:
print "Error: unable to start thread"
def print_time(self,bleh):
print bleh
print "The text area value is %s" % self.text_area.get()
boom=5
while boom >0:
time.sleep(1)
self.text_area.delete(0, END)
self.text_area.insert(0, boom)
print(boom)
boom -=1
root = Tk()
app = App(root)
root.mainloop()
threading.Thread(target=self.print_time("I am in print_time"))
This will not do what you want it to do. What happens here is that the function self.print_time is called and its return value is then passed to the constructor of threading.Thread.
You need to create the thread like this:
t = threading.Thread(target=self.print_time, args=("I am in print_time",))