Rithvik Muthuvelu
Rithvik Muthuvelu

Reputation: 31

Tkinter background colour changer

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

Answers (2)

TheLizzard
TheLizzard

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

JoshG
JoshG

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

Related Questions