Reputation: 31
I am quite new to tkinter. I am trying to create a tkinter app where there is a button that says "start colour changer" and then the background of my tkinter app changes its background. That part works fine but I coded it so that when you click the "start colour changer" the background constantly changes and a new button saying "Stop colour changer" appears. I think the stop colour changer is the problem because when I click the "Stop colour changer" the colour changer keeps going! Please can you help me.
Here is my code:
from tkinter import *
root = Tk()
def opposite_of_get_colour():
colours2 = ['white']
for colour in colours2:
while True:
yield colour
def get_colour():
colours = ['#e0ffff', '#7FDBFF', '#01FF70', '#FFFFFF', '#DDDDDD', '#AAAAAA', '#FF851B']
while True:
for c in colours:
yield c
def start():
stopButton = Button(root, text = "Stop colour changer", command = stop)
stopButton.grid(row = 8, column = 0)
root.configure(background=next(colour_getter))
root.after(1000, start) # run this function again after 1000ms
colour_getter = get_colour()
startButton = Button(root, text="Start colour changer",command=start)
startButton.grid(row = 7, column = 0)
def stop():
root.configure(background=next(no_colour_getter))
new_stop_button = Button(root, text = "Stop coour change.", state = DISABLED)
new_stop_button.grid(row = 8, column = 0)
no_colour_getter = opposite_of_get_colour()
root.mainloop()
Upvotes: 0
Views: 90
Reputation: 7710
I think this is what you are trying to do:
from tkinter import *
def get_colour():
colours = ['#e0ffff', '#7FDBFF', '#01FF70', '#FFFFFF', '#DDDDDD', '#AAAAAA', '#FF851B']
while True:
for c in colours:
yield c
def _start():
global flag_to_stop
if not flag_to_stop:
root.configure(background=next(colour_getter))
root.after(1000, _start) # run this function again after 1000ms
def start():
global flag_to_stop
flag_to_stop = False
stopButton.grid(row=8, column=0)
_start()
def stop():
global flag_to_stop
flag_to_stop = True
# Remove the button from the window:
stopButton.grid_forget()
root.configure(background="white")
root = Tk()
root.geometry("100x100")
colour_getter = get_colour()
startButton = Button(root, text="Start colour changer", command=start)
startButton.grid(row=7, column=0)
stopButton = Button(root, text="Stop colour changer", command=stop)
# Don't grid `stopButton` for now
root.mainloop()
There is a flag (flag_to_stop
). When the flag is True
, the colour changing loop stops.
Upvotes: 0
Reputation: 6745
A successful after()
call will return a cancel ID. This can be used to stop the scheduled function from running by calling after_cancel()
.
Here's an example using your code:
from tkinter import *
root = Tk()
def opposite_of_get_colour():
colours2 = ['white']
for colour in colours2:
while True:
yield colour
def get_colour():
colours = ['#e0ffff', '#7FDBFF', '#01FF70', '#FFFFFF', '#DDDDDD', '#AAAAAA', '#FF851B']
while True:
for c in colours:
yield c
def start():
stopButton = Button(root, text = "Stop colour changer", command = stop)
stopButton.grid(row = 8, column = 0)
root.configure(background=next(colour_getter))
# define global variable so other functions can access the current id
# if using classes, you might want to use an instance variable for this
global id
# store the current id
id = root.after(1000, start) # run this function again after 1000ms
colour_getter = get_colour()
startButton = Button(root, text="Start colour changer", command=start)
startButton.grid(row = 7, column = 0)
def stop():
root.configure(background=next(no_colour_getter))
new_stop_button = Button(root, text = "Stop colour change.", state = DISABLED)
new_stop_button.grid(row = 8, column = 0)
# cancel invoking the callback with the latest id
root.after_cancel(id)
no_colour_getter = opposite_of_get_colour()
root.mainloop()
Upvotes: 1