如何对多个对象使用 itertools.cycle?

How do I use itertools.cycle with multiple objects?

我正在尝试通过 itertools.cycle 迭代器中定义的颜色循环在 Tkinter 中按下按钮的颜色:

colour=itertools.cycle('blue', 'green', 'orange', 'red', 'yellow', 'white')

def changeColour(button):
    button.configure(bg = next(colour))

LT = Button(root, width=16, height=8, bg = 'white', command=lambda: changeColour(LT))
LT.place(x=10, y=10)

LM = Button(root, width=16, height=8, bg = 'white', command=lambda: changeColour(LM))
LM.place(x=10, y=150)

LB = Button(root, width=16, height=8, bg = 'white', command=lambda: changeColour(LB))
LB.place(x=10, y=290)

但是,每次按下按钮都会影响下一次按钮按下的迭代中的起始位置,这意味着每个按钮都会跳转到分配给先前单击的按钮的值之后 next(colour) 的值。我试图让每个按钮执行独立于另一个按钮当前颜色的背景颜色的完整循环。我怎样才能做到这一点?

如果您希望每个按钮独立,则需要为每个按钮单独设置一个 cycle。一种方法是创建一个函数工厂来构建您需要调用的函数:

COLOURS = ('blue', 'green', 'orange', 'red', 'yellow', 'white')

def colour_changer(button, colours=COLOURS):
    """Creates a callback to change the colour of the button."""
    colour_cycle = itertools.cycle(colours)
    def command():
        """The callback to change a single button's colour."""
        button.configure(bg=next(colour_cycle))
    return command

然后在创建每个按钮后调用它:

LT = Button(root, width=16, height=8, bg = 'white')
LT.configure(command=colour_changer(LT))

您还可以查看绑定,它会将按钮传递给您的回调。

每个按钮都知道它当前的背景颜色。下面使用字典以循环方式将当前颜色映射到下一个颜色。

from tkinter import *
root = Tk()

colors = ('blue', 'green', 'orange', 'red', 'yellow', 'white', 'blue')
cd = dict(zip(colors, colors[1:]))
#print(cd)

def changeColour(button):
    button['bg'] = cd[button['bg']]

LT = Button(root, width=16, height=8, bg = 'white',
            command=lambda: changeColour(LT))
LT.place(x=10, y=10)

LM = Button(root, width=16, height=8, bg = 'white',
            command=lambda: changeColour(LM))
LM.place(x=10, y=150)

LB = Button(root, width=16, height=8, bg = 'white',
            command=lambda: changeColour(LB))
LB.place(x=10, y=290)

root.mainloop()