0

I am trying to create a color changing button in tkinter. Here's my code:

import tkinter as tk

window = tk.Tk()

btn = tk.Button(window, text='Button')
btn.pack(padx=50, pady=30)

rainbow_colors = ['red','purple','yellow','orange','blue',
                  'lightblue','green','violet','gray','cyan']
color_iterator = iter(rainbow_colors)

def ButtonUpdate():
    try:    
        color = next(color_iterator)    
        btn.config(bg=color)
    except StopIteration:
        return
    window.after(500, ButtonUpdate)

ButtonUpdate()

window.mainloop()

While this does work I want the button to keep changing it's color. In my code it traverses the list once and then stops.

Green
  • 82
  • 9
Kritarth
  • 31
  • 10

3 Answers3

3

Try below solution, using cycle of itertools to continue cycle in a list, explanation and steps given in a comment

import tkinter as tk
# 1) Import module
from itertools import cycle

window = tk.Tk()

btn = tk.Button(window, text='Button')
btn.pack(padx=50, pady=30)

rainbow_colors = ['red','purple','yellow','orange','blue',
                  'lightblue','green','violet','gray','cyan']
color_iterator = iter(rainbow_colors)
#2) Create object of cycle
licycle = cycle(rainbow_colors)
def ButtonUpdate():
    try:    
        # 3) Fetch next element from cycle object
        color = next(licycle)    
        btn.config(bg=color)
    except StopIteration:
        return
    window.after(500, ButtonUpdate)

ButtonUpdate()

window.mainloop()
Hetal Thaker
  • 556
  • 4
  • 9
3

I am just adding another way you can approach this easily, without importing any external modules or anything just by using simple python indexing and if conditions:

idx = 0
def ButtonUpdate(idx):
    if idx >= len(rainbow_colors): # Check if idx is out of list, then reset to 0
        idx = 0
    btn.config(bg=rainbow_colors[idx])
    idx += 1 
    window.after(500,ButtonUpdate,idx)

ButtonUpdate(idx)

You can also remove all your code related to iter as its no longer needed. You could also just use global but parameter seems more efficient to me.

Cool Cloud
  • 10,863
  • 3
  • 10
  • 32
1

Try this:

import tkinter as tk

def my_iterator_looper(_list):
    while True:
        for i in _list:
            yield i

window = tk.Tk()

btn = tk.Button(window, text='Button')
btn.pack(padx=50, pady=30)

rainbow_colors = ['red','purple','yellow','orange','blue',
                  'lightblue','green','violet','gray','cyan']
color_iterator = my_iterator_looper(rainbow_colors)

def ButtonUpdate():
    try:    
        color = next(color_iterator)    
        btn.config(bg=color)
    except StopIteration:
        return
    window.after(500, ButtonUpdate)

ButtonUpdate()

window.mainloop()

I created my own iterator that uses a while True loop and yield to loop over the values continually. For more on how yield works read this

TheLizzard
  • 4,696
  • 2
  • 8
  • 22