Label Is Not Shown When Called From Other Tkinter Program - python

I was writing a program with a start page, and two programs that are called from that start page. Both of the subprograms work by themselves. However, when I put them into my start page, the stopwatch timing label doesn't show up. If you are wondering, I put them into my program by doing:
import program
program.function()
Here is my start page program:
from Tkinter import *
class start_page:
def __init__(self,master):
self.master = master
self.frame = Frame(self.master)
self.countdown = Button(master, text = "Timer", command = self.c).pack()
self.stopwatch_butt = Button(master,text="Stopwatch",command=self.g).pack()
def g(self):
import stopwatch
stopwatch.f()
def c(self):
import timer_prog
timer_prog.timer()
self.master.after_cancel(timer_prog)
def main():
root = Tk()
s = start_page(root)
root.title("Timer Suite: Brian Ton")
root.mainloop()
main()
If I run this program, the timer program works fine, but the stopwatch doesn't show its label, only its buttons. I tried to clear all Tk after functions, and that didn't work, and I also tried to run the stopwatch program first, to no avail.
Here is my stopwatch program:
from Tkinter import *
import datetime
def s():
start.config(state='disabled')
stop.config(state="normal")
reset.config(state='disabled')
Start()
def Start():
if reset['state'] == 'disabled' and stop['state'] == 'normal':
hidden.set(str(int(hidden.get())+1))
root.update()
root.after(1000,Start)
curr = hidden.get()
g.set(str(datetime.timedelta(seconds=int(curr))))
print g.get()
else:
return None
def Stop():
start.config(state='disabled')
stop.config(state='disabled')
reset.config(state="normal")
def Reset():
start.config(state="normal")
stop.config(state="disabled")
reset.config(state='disabled')
hidden.set('0')
g.set(str(datetime.timedelta(seconds=0)))
def f():
global root,frame,master,hidden,g,timelabel,start,stop,reset
root = Tk()
frame = Frame(root)
master = root
hidden = StringVar()
g = StringVar()
hidden.set('0')
timelabel = Label(master,textvariable=g)
g.set(str(datetime.timedelta(seconds=int(0))))
timelabel.grid(row=1,column=2)
start = Button(master,text="Start",command = s,state="normal")
stop = Button(master,text="Stop",command = Stop,state = "disabled")
reset = Button(master,text="Reset",command = Reset,state = "disabled")
start.grid(row=2,column=1)
stop.grid(row=2,column=2)
reset.grid(row=2,column=3)
root.update()
root.mainloop()
And here is my timer program:
from Tkinter import *
import datetime
def get_seconds(h,m,s):
hr_sec = h * 3600
m_sec = m * 60
return hr_sec+m_sec+s
def timerstartstop():
hours = hour_entry.get()
minutes = minute_entry.get()
sec = second_entry.get()
if hours == "":
hours = 0
hour_entry.insert(0,"0")
if minutes == "":
minutes = 0
minute_entry.insert(0,"0")
if sec == "":
sec = 0
second_entry.insert(0,"0")
c = get_seconds(int(hours), int(minutes), int(sec))
global s
s = StringVar(master)
s.set(c)
if startstop['text'] == 'Stop':
global curr
curr = shown
s.set(-1)
if startstop['text'] == 'Reset':
startstop.config(text="Start")
s.set(c)
root.update()
shown.set(str(datetime.timedelta(seconds=int(s.get()))))
return None
countdown()
import winsound
def countdown():
startstop.config(text="Stop")
global shown
good = True
shown = StringVar(master)
shown.set(str(datetime.timedelta(seconds=int(s.get()))))
L = Label(master,textvariable=shown).grid(row=1,column=2)
if int(s.get()) == 0:
startstop.config(text="Reset")
while startstop['text'] != "Start":
root.update()
winsound.Beep(500,500)
elif int(s.get()) < 0:
good = False
shown.set(curr.get())
startstop.config(text="Reset")
else:
if good:
s.set(str(int(s.get())-1))
root.after(1000,countdown)
def ex():
root.after_cancel(countdown)
root.destroy()
def timer():
global root
global master
global frame
root = Tk()
master = root
frame = Frame(master)
global hour_entry
hour_entry = Entry(master,width=3)
hour_entry.grid(row=0,column=0)
colon_l = Label(master,text=':').grid(row=0,column=1)
global minute_entry
minute_entry = Entry(master,width=2)
minute_entry.grid(row=0,column=2)
colon_l2 = Label(master,text=':').grid(row=0,column=3)
global second_entry
second_entry = Entry(master,width=2)
second_entry.grid(row=0,column=4)
global startstop
startstop = Button(master,text="Start",command=timerstartstop)
e = Button(master,text="Exit",command=ex).grid(row=1,column=3)
startstop.grid(row=0,column=5)
root.mainloop()
In addition, I tried to run these two programs from a different starting menu that used the console, which worked.
The console program is:
import timer_prog
timer_prog.timer()
raw_input('next')
import stopwatch
stopwatch.f()
Attached are some screenshots of what the stopwatch program should look like vs what it does look like when called from the starting program.
Note: I can tell the program is running from the starting page, as it prints the current time each second. Also, I attached some screenshots
Stopwatch Program Run Directly
Stopwatch Program Run From The Start Page

Tkinter program should use only one Tk() - to create main window - and one mainloop() - to control all windows and widgets. If you use two Tk() and two mainloop() then it has problem - for example get()/set() may not work.
Subwindows should use Toplevel() instead of Tk().
Function which starts program (ie. run()) could run with parameter window (def run(window)) and then you can execute it as standalone program with
root = Tk()
run(root)
root.mainloop()
or after importing
run(Toplevel())
(without maniloop())
You can use if __name__ == "__main__" to recognize if program starts as standalone.
Example
main.py
from Tkinter import *
class StartPage:
def __init__(self, master):
self.master = master
master.title("Timer Suite: Brian Ton")
Button(master, text="Timer", command=self.run_timer).pack()
Button(master, text="Stopwatch", command=self.run_stopwatch).pack()
def run_stopwatch(self):
import stopwatch
window = Toplevel()
stopwatch.run(window)
def run_timer(self):
import timer_prog
window = Toplevel()
timer_prog.timer(window)
self.master.after_cancel(timer_prog)
def main():
root = Tk()
StartPage(root)
root.mainloop()
main()
stopwatch.py
from Tkinter import *
import datetime
def pre_start():
start_button.config(state='disabled')
stop_button.config(state='normal')
reset_button.config(state='disabled')
start()
def start():
global current_time
# stop_button['state'] can be 'normal' or 'active' so better use ` != 'disabled'`
if reset_button['state'] == 'disabled' and stop_button['state'] != 'disabled':
current_time += 1
time_var.set(str(datetime.timedelta(seconds=current_time)))
print(time_var.get())
master.after(1000, start)
def stop():
start_button.config(state='disabled')
stop_button.config(state='disabled')
reset_button.config(state='normal')
def reset():
global current_time
start_button.config(state='normal')
stop_button.config(state='disabled')
reset_button.config(state='disabled')
current_time = 0
time_var.set(str(datetime.timedelta(seconds=0)))
def run(window):
global master
global current_time, time_var
global start_button, stop_button, reset_button
master = window
current_time = 0
time_var = StringVar()
time_var.set(str(datetime.timedelta(seconds=0)))
time_label = Label(window, textvariable=time_var)
time_label.grid(row=1, column=2)
start_button = Button(master, text='Start', command=pre_start, state='normal')
stop_button = Button(master, text='Stop', command=stop, state='disabled')
reset_button = Button(master, text='Reset', command=reset, state='disabled')
start_button.grid(row=2, column=1)
stop_button.grid(row=2, column=2)
reset_button.grid(row=2, column=3)
if __name__ == '__main__':
# it runs only in standalone program
root = Tk()
run(root)
root.mainloop()

Related

Text in tkinter

I want that when the "Start" button is pressed, it executes code and counts from 3 (3... 2... 1... Ready!), with delay between each and printing the numbers in the program window. I used tkinter. But I can't get the countdown to appear when I press the "Start" button. And I don't know how to add the code that is executed after pressing the button.
import tkinter as tk
from tkinter import ttk
import time
class Aplicacion:
def __init__(self,master):
self.master=master
self.master.title('Title')
self.master.geometry('290x50')
self.inicializar_gui()
def inicializar_gui(self):
lbl_bienvenido=tk.Label(self.master,text='Hi!',font=('Helvetica',10))
lbl_bienvenido.place(x=0,y=0)
btn_login=tk.Button(self.master,text='Start')
btn_login['command']=self.comando
btn_login.place(x=10,y=23)
def comando(self):
entry = ttk.Entry(state=tk.DISABLED, takefocus=False)
entry.place(x=63, y=25)
entry.insert(0, "1...")
# print("3")
# time.sleep(1)
# print("2")
# time.sleep(1)
# print("1")
# time.sleep(1)
# print("Ready!")
def main ():
root = tk.Tk()
ventana = Aplicacion(root)
root.mainloop()
if __name__ == "__main__":
main()
here is an exemple that you could adjust to your need :
import tkinter
root = tkinter.Tk()
txt = tkinter.Text(root)
a = 4
def countdown():
global a
if a>0:
txt.delete('1.0','end')
a -=1
txt.insert('0.0',str(a))
root.after(1000,countdown)
if a == 0 :
txt.delete('1.0','end')
txt.insert('0.0','Ready!!')
btn = tkinter.Button(root,text = 'START',command = countdown)
txt.pack()
btn.pack()
root.mainloop()

while loop/thread problem with stopwatch program

So I am making a stopwatch program with tkinter.
At the moment, I am in the process of implementing a stop button for the stopwatch.
I can start the stopwatch and it will update the Label fine but my end button isn't working and I can't seem to figure out why.
Here's my code so far:
from tkinter import *
from time import sleep
import threading
root = Tk()
root.title("Clock")
class Buttons:
def __init__(self, master):
self.menu = Menu(master)
master.config(menu=self.menu)
self.menu.add_command(label="Stopwatch")
self.menu.add_command(label="Timer")
self.menu.add_command(label="Quit", command=quit)
self.stopwatchStart = Button(master, text="Start", command=self.test_start)
self.stopwatchStart.config(height=2, width=5)
self.stopwatchStart.grid(row=0)
self.stopwatchEnd = Button(master, text="End", command=self.stopwatch_End)
self.stopwatchEnd.config(height=2, width=5)
self.stopwatchEnd.grid(row=1)
self.labelSeconds = Label(master, text="Seconds:")
self.labelSeconds.grid(row=0, column=1)
self.stopwatchSeconds = Label(master, text="0")
self.stopwatchSeconds.grid(row=0, column=2)
def test_start(self):
print("Starting thread")
t = threading.Thread(target=self.stopwatch_Start)
t.setDaemon(True)
t.start()
def stopwatch_Start(self, test=False):
print("Stopwatch started")
stopwatch_seconds = "0"
stopwatchBreak = test
print(f"stopwatchBreak == {stopwatchBreak}")
while not stopwatchBreak:
print(stopwatch_seconds)
stopwatch_seconds = int(stopwatch_seconds)
stopwatch_seconds += 1
self.stopwatchSeconds.config(text=stopwatch_seconds)
root.update()
sleep(1)
print("Stopping stopwatch")
return
def stopwatch_End(self):
Buttons.stopwatch_Start(self, True)
print("Attempting to end")
b = Buttons(root)
root.mainloop()
I am using threading to run the stop watch and the window from tkinter at the same time by the way.
Also I have put several print() across the functions to see what is succeeding and what isn't. I think the problem may have something to do with the thread in test_start(). The loop that won't end when I click the end button is in stopwatch_Start(). It just keeps counting up.
I have received no error messages
Does anyone have any suggestions/alternatives to stopping the stopwatch?
look at this code
def stopwatch_End(self):
Buttons.stopwatch_Start(self, True)
print("Attempting to end")
this is your problem =>
Buttons.stopwatch_Start(self, True)
correct this with:
self.stopwatch_Start(True)
here you are call "stopwatch" on the class Buttons, this is an unbound function!!!
"Buttons.stopwatch" is different than "self.stopwatch" the later is bound to the instance.
from tkinter import *
from time import sleep
from threading import Thread
from threading import Event
root = Tk()
root.title("Clock")
class Buttons:
def __init__(self, master):
self.evt = Event()
self.menu = Menu(master)
master.config(menu=self.menu)
self.menu.add_command(label="Stopwatch")
self.menu.add_command(label="Timer")
self.menu.add_command(label="Quit", command=quit)
self.stopwatchStart = Button(master, text="Start", command=self.test_start)
self.stopwatchStart.config(height=2, width=5)
self.stopwatchStart.grid(row=0)
self.stopwatchEnd = Button(master, text="End", command=self.stopwatch_End)
self.stopwatchEnd.config(height=2, width=5)
self.stopwatchEnd.grid(row=1)
self.labelSeconds = Label(master, text="Seconds:")
self.labelSeconds.grid(row=0, column=1)
self.stopwatchSeconds = Label(master, text="0")
self.stopwatchSeconds.grid(row=0, column=2)
def test_start(self):
print("Starting thread")
t = Thread(target=self.stopwatch_Start)
t.setDaemon(True)
t.start()
def stopwatch_Start(self, test=False):
print("Stopwatch started")
stopwatch_seconds = "0"
stopwatchBreak = test
print(f"stopwatchBreak == {stopwatchBreak}")
# self.evt.is_set() will force the loop to check its actually state if it True or not
while not self.evt.is_set():
print(stopwatch_seconds)
stopwatch_seconds = int(stopwatch_seconds)
stopwatch_seconds += 1
self.stopwatchSeconds.config(text=stopwatch_seconds)
root.update()
sleep(1)
print("Stopping stopwatch")
return
def stopwatch_End(self):
#we set self.evt to True so that the while loop will be broken
self.evt.set()
print("Attempting to end")
b = Buttons(root)
root.mainloop()

tkinter mouse click counter won't break out of my countdown loop

I'm trying to write a little program in python using tkinter, to count the number of times the mouse clicks a button in 60 sec, but I have a problem: I can't break the countdown loop.
Below is my code:
from tkinter import *
class Application(Frame):
def __init__(self,master):
super(Application,self).__init__(master)
self.pack()
self.bttn_clicks = 0
self.createWidgets()
def createWidgets(self):
self.labelvariable = StringVar()
self.labelvariable.set("60")
self.thelabel = Label(self,textvariable = self.labelvariable,font=('Helvetica',50))
self.thelabel.pack(side=TOP)
self.firstButton = Button(self, text="Start", command=self.update_count)
self.firstButton.pack(side=TOP)
def update_count(self):
self.bttn_clicks += 1
self.firstButton["text"] = "Counter: " + str(self.bttn_clicks)
if self.bttn_clicks == 1:
countdown(1559)
def countdown(timeInSeconds):
mins, secs = divmod(timeInSeconds, 60)
timeformat = "{1:02d}".format(mins, secs)
app.labelvariable.set(timeformat)
root.after(1000, countdown, timeInSeconds-1)
if __name__ == '__main__':
root = Tk()
root.title("Timer")
app = Application(root)
root.mainloop()
What I would do is keep everything within the class. Using an outside function just makes things harder to manage.
That said you should use IntVar() instead of string var as this will aid us in keeping track of the time.
My below code will check first if the timer is at 60. If so then start count down and add to counter. When the counter reaches zero the button has its command disabled and it no longer adds to the counter.
The other thing I changed was adding a manager method for the timer. Because we are now using IntVar() all we need to do is a get() command followed by a -1 and an after() statement to keep the timer running until zero.
I also cleaned up your code a little to follow the PEP8 standard.
import tkinter as tk
class Application(tk.Frame):
def __init__(self,master):
super(Application,self).__init__(master)
self.bttn_clicks = 0
self.labelvariable = tk.IntVar()
self.create_widgets()
def create_widgets(self):
self.labelvariable.set(60)
self.thelabel = tk.Label(self, textvariable=self.labelvariable, font=('Helvetica',50))
self.thelabel.pack(side=tk.TOP)
self.firstButton = tk.Button(self, text="Start", command=self.update_count)
self.firstButton.pack(side=tk.TOP)
def update_count(self):
if self.labelvariable.get() == 60:
self.manage_countdown()
if self.labelvariable.get() != 0:
self.bttn_clicks += 1
self.firstButton.config(text="Counter: {}".format(self.bttn_clicks))
else:
self.firstButton.config(command=None)
def manage_countdown(self):
if self.labelvariable.get() != 0:
self.labelvariable.set(self.labelvariable.get() - 1)
self.after(1000, self.manage_countdown)
if __name__ == '__main__':
root = tk.Tk()
root.title("Timer")
app = Application(root).pack()
root.mainloop()

only last modification to Label being shown in Python - Tkinter . Why?

I am learning GUI development using Tkinter. I want to show multiple messages on the label which I have stored in a string. I used sleep to view the changes.However only the last message string is shown at execution.
from tkinter import *
import time
master = Tk()
def onClick():
for i in range(0,len(list_of_str)):
w.configure(text=list_of_str[i])
time.sleep(5)
list_of_str = ['first','second','third','fourth','fifth']
w = Label(master, text="Hello, world!")
b = Button(master,text='Click me',command = onClick)
w.pack()
b.pack()
mainloop()
I am a noobie. So thanks for helping !
A simple solution to your problem is to use a combination of the try/except method and using after().
In tkinter sleep() will pause the application instead of providing a timer. For tkinter you want to use the after() method to scheduled an event after a set amount of time instead. The after() method is meant for this exact problem and is what you will always use in tkinter for a delayed event.
In my below example I modified your onClick function to take 1 argument and to use that in our after() method to select the next item in the list after 5 seconds. Note that for the after() method time is done in milliseconds so 5000 is 5 seconds.
from tkinter import *
master = Tk()
def onClick(ndex):
try:
w.configure(text=list_of_str[ndex])
master.after(5000, onClick, ndex+1)
except:
print("End of list")
list_of_str = ['first','second','third','fourth','fifth']
w = Label(master, text="Hello, world!")
b = Button(master,text='Click me',command = lambda: onClick(0))
w.pack()
b.pack()
mainloop()
I think you want this:
from tkinter import *
import time
master = Tk()
global i
i = 0
def onClick():
master.after(1, change)
def change():
global i
if i == len(list_of_str):
pass
else:
w.configure(text=list_of_str[i])
i += 1
master.after(1000, onClick)
list_of_str = ['first','second','third','fourth','fifth']
w = Label(master, text="Hello, world!")
b = Button(master,text='Click me',command = onClick)
w.pack()
b.pack()
mainloop()
time.sleep is a no-no in tkinter. I advise you make your gui in a class and it wil be easier.
example with class:
import tkinter as tk
from tkinter import *
class GUI:
def __init__(self, master):
self.list_of_str = ['first','second','third','fourth','fifth']
self.count = 0
self.master = master
self.w = Label(master, text="Hello, world!")
self.w.pack()
self.b = Button(master,text='Click me',command = self.onClick)
self.b.pack()
def onClick(self, event=None):
if self.count == len(self.list_of_str):
pass
else:
self.w.configure(text=self.list_of_str[self.count])
self.count += 1
self.master.after(1000, self.onClick)
def main():
root = tk.Tk()
app = GUI(root)
root.mainloop()
if __name__ == '__main__':
main()

Tkinter - How to stop a loop with a stop button?

I have this program which beeps every second until it's stopped. The problem is that after I press "Start" and the beeps starts, I cannot click the "Stop" button because the window freezes. Any help is welcome.
#!/usr/bin/python
import Tkinter, tkMessageBox, time, winsound, msvcrt
running = True
Freq = 2500
Dur = 150
top = Tkinter.Tk()
top.title('MapAwareness')
top.geometry('200x100') # Size 200, 200
def start():
sec = 0
while running:
if sec % 1 == 0:
winsound.Beep(Freq, Dur)
time.sleep(1)
sec += 1
def stop():
running = False
startButton = Tkinter.Button(top, height=2, width=20, text ="Start", command = start)
stopButton = Tkinter.Button(top, height=2, width=20, text ="Stop", command = stop)
startButton.pack()
stopButton.pack()
top.mainloop()
There are several things wrong with your code. First of all you shouldn't use time.sleep() in a Tkinter program because it interferes with the mainloop(). Instead one typically uses the universal widget method .after() to schedule a function to run after a specified delay.
Secondly you're not using global variables correctly. When you assign a value to a named variable in a function, it will create a local variable unless that name has been previous declared global. So for instance, your stop() function is creating a local variable named running and setting its value to 0, not changing the value of the global variable with the same name.
The previous rule doesn't apply to just referencing (reading) the current value of a variable. That is why it was OK to not have declared Freq and Dur globals in start().
Another problem is with the sec % 1 == 0 in your start() function. Any value % 1 is 0. To check odd/evenness use sec % 2.
Here's a working version which has also been reformatted to follow PEP 8 - Style Guide for Python Code more closely.
try:
import tkinter as tk
except ModuleNotFoundError:
import Tkinter as tk # Python 2.
import winsound
FREQ = 2500
DUR = 150
after_id = None
secs = 0
def beeper():
global after_id
global secs
secs += 1
if secs % 2 == 0: # Every other second.
winsound.Beep(FREQ, DUR)
after_id = top.after(1000, beeper) # Check again in 1 second.
def start():
global secs
secs = 0
beeper() # Start repeated checking.
def stop():
global after_id
if after_id:
top.after_cancel(after_id)
after_id = None
if __name__ == '__main__':
top = tk.Tk()
top.title('MapAwareness')
top.geometry('200x100')
startButton = tk.Button(top, height=2, width=20, text="Start", command=start)
stopButton = tk.Button(top, height=2, width=20, text="Stop", command=stop)
startButton.pack()
stopButton.pack()
top.mainloop()
Update
Since this answer has become fairly popular, I'd like touch on another slightly more advanced topic — namely how making the code more object-oriented would simplify things by eliminating the need almost all of the global variables.
try:
import tkinter as tk
except ModuleNotFoundError:
import Tkinter as tk # Python 2.
import winsound
FREQ = 2500
DUR = 150
class Application(tk.Frame, object):
def __init__(self, master=None):
super(Application, self).__init__(master) # Call base class initializer.
self.after_id = None
self.secs = 0
# Create widgets,
startButton = tk.Button(top, height=2, width=20, text="Start", command=self.start)
stopButton = tk.Button(top, height=2, width=20, text="Stop", command=self.stop)
startButton.pack()
stopButton.pack()
def beeper(self):
self.secs += 1
if self.secs % 2 == 0: # Every other second.
winsound.Beep(FREQ, DUR)
self.after_id = top.after(1000, self.beeper) # Check again in 1 second.
def start(self):
self.secs = 0
self.beeper() # Start repeated checking.
def stop(self):
if self.after_id:
top.after_cancel(self.after_id)
self.after_id = None
if __name__ == '__main__':
top = tk.Tk()
app = Application()
app.master.title('MapAwareness')
app.master.geometry('200x100')
app.mainloop()
You code have top.mainloop() which has a while loop running inside it and on top of that you also have a while loop inside def start():. So it is like loop inside loop.
You can create a function that does what you want for the body of the loop. It should do exactly one iteration of the loop. Once it is done, it needs to arrange for itself to be called again some time in the future using after. How far in the future defines how fast your loop runs.
And you can then use after_cancel to cancel the event. Below code worked for me
import Tkinter, tkMessageBox, time, winsound, msvcrt
Freq = 2500
Dur = 150
top = tkinter.Tk()
top.title('MapAwareness')
top.geometry('200x100') # Size 200, 200
def start():
global job1
if running == True:
winsound.Beep(Freq, Dur)
job1 = top.after(1000, start) # reschedule event in 1 seconds
def stop():
global job1
top.after_cancel(job1)
startButton = tkinter.Button(top, height=2, width=20, text ="Start", command = start)
stopButton = tkinter.Button(top, height=2, width=20, text ="Stop", command = stop)
startButton.pack()
stopButton.pack()
#top.after(1000, start)
top.mainloop()
The problem is that the while loop in start() blocks the GUI handler mainloop(). Try using Tk.after() in start():
def start(force=True):
global running
if force:
running = True
if running:
winsound.Beep(Freq, Dur)
top.after(1000, start, False)
And change stop():
def stop():
global running
running = False
Beaten to the punch again but here goes nothing. As above use the after function to prevent the mainloop blocking.
See:
tkinter: how to use after method
#!/usr/bin/python
import Tkinter, tkMessageBox, time
Freq = 2500
Dur = 150
top = Tkinter.Tk()
top.title('MapAwareness')
top.geometry('200x100') # Size 200, 200
def start():
print ("Beep")
top.after(1000, start)
def stop():
print ("Stop")
top.quit()
startButton = Tkinter.Button(top, height=2, width=20, text ="Start", command = start)
stopButton = Tkinter.Button(top, height=2, width=20, text ="Stop", command = stop)
startButton.pack()
stopButton.pack()
top.mainloop()
I used thread and global variable to fit your need. Not so complicated if you understand how they work. Just an addition of few lines and minor change to your existing line, and it works. Look through to see the changes made to your original code.
#!/usr/bin/python
import tkinter
from tkinter import messagebox
import time, winsound, msvcrt
from threading import Thread
running = True
Freq = 2500
Dur = 150
top = tkinter.Tk()
top.title('MapAwareness')
top.geometry('200x100') # Size 200, 200
def button_click():
global running #create global
running = True
# Create new thread
t = Thread(target = start)
# Start new thread
t.start()
def start():
sec = 0
while running:
if running == False:
break
if sec % 1 == 0:
winsound.Beep(Freq, Dur)
time.sleep(1)
sec += 1
def stop():
global running #create global
running = False
startButton = tkinter.Button(top, height=2, width=20, text ="Start", command = button_click) #Change to call button_click instead start
stopButton = tkinter.Button(top, height=2, width=20, text ="Stop", command = stop)
startButton.pack()
stopButton.pack()
top.mainloop()
from threading import Thread
def stttart():
t1=Thread(target=start)
t1.start()
def start():
...
def stop():
...
startButton = Tkinter.Button(top, height=2, width=20, text ="Start", command = stttart)
stopButton = Tkinter.Button(top, height=2, width=20, text ="Stop", command = stop)
startButton.pack()
stopButton.pack()
https://www.geeksforgeeks.org/how-to-use-thread-in-tkinter-python/
last year, this had been my big problem for some months

Categories