Python имеет итераторов . Они похожи на списки, но элементы в итераторе генерируются по мере необходимости, а не перечисляются полностью во время определения. Вот пример бесконечного итератора, созданного путем обертывания кортежа с itertools.cycle :
In [119]: import itertools
In [120]: color=itertools.cycle(('blue', 'green', 'orange', 'red', 'yellow'))
In [121]: color
Out[121]: <itertools.cycle object at 0x9a1846c>
Вы можете извлечь значения из итератора, применив к нему функцию next
:
In [122]: next(color)
Out[122]: 'blue'
In [123]: next(color)
Out[123]: 'green'
Если бы мы продолжали вызывать next
достаточное количество раз, итератор достиг бы yellow
, затем вернулся бы к циклу и снова выдал blue
. Таким образом, это бесконечный итератор, и он прекрасно описывает, какие цвета мы хотим для кнопки, не связываясь с какой-либо переменной счетчика.
Таким образом, вместо подсчета с помощью self.bttn_clicks
, вы можете использовать этот итератор следующим образом:
import Tkinter as tk
import itertools
class App(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self,master)
self.master=master
self.grid()
self.colors=itertools.cycle(('blue', 'green', 'orange', 'red', 'yellow'))
self.bttn1=tk.Button(self, text='Click Me!', bg=next(self.colors),
command=self.change_color)
self.bttn1.grid()
def change_color(self):
color=next(self.colors)
self.bttn1.configure(background=color)
root=tk.Tk()
root.title('Color Button')
root.geometry('200x85')
app=App(root)
root.mainloop()
Обратите внимание, что кнопка подсвечивается, когда мышь находится над ней. Поэтому, когда вы нажимаете кнопку, она выглядит серой. Вы должны убрать мышь с кнопки, чтобы увидеть цвета.
код
if self.bttn_clicks + 1:
говорит Python вычислить выражение self.bttn_clicks + 1
. Поскольку self.bttn_clicks
начинается с 0, это выражение равно 1. В Python 0 считается логическим значением false, в то время как все остальные числа имеют логическое значение true (даже float('nan')
и float('inf')
!). Таким образом, if self.bttn_clicks + 1
оценивается как True
и if-block
выполняется.
Таким образом, кнопка имеет синий цвет:
self.bttn1.configure(background = "blue")
Далее условное
if self.bttn_clicks + 2:
оценивается как 0+2
, что эквивалентно 2
, что опять-таки True,
поэтому следующий if-block
также выполняется. Теперь кнопка установлена в зеленый цвет. И так далее.
Очевидно, это не то, что мы хотим. Вместо этого увеличьте значение self.bttn_clicks
на единицу, но верните его в ноль, если оно превышает индекс, соответствующий последнему цвету (посмотрите, насколько это трудоемко по сравнению с использованием итератора?):
self.bttn_clicks=(self.bttn_clicks+1)%5
и проверьте, какое значение self.bttn_clicks
теперь равно:
if self.bttn_clicks == 0:
self.bttn1.configure(background = "blue")
elif self.bttn_clicks == 1:
self.bttn1.configure(background = "green")
...