我想编写一个程序,在给定的时间段内将Tkinter窗口的背景从初始的十六进制颜色淡化为最终的十六进制颜色,同时显示其间的一些颜色。 (取消注释第99行,print time, hex_color_t
,如果不清楚,应澄清我的意思。)
以下是代码:
from Tkinter import *
from ttk import *
import re
class InvalidColor(Exception):
pass
def color_to_hex(color):
MIN_COLOR = 0
MAX_COLOR = 255
try:
if color >= MIN_COLOR and color <= MAX_COLOR:
try:
hex_str = hex(color)[2:]
except TypeError:
raise InvalidColor
if len(hex_str) < 2:
hex_str = "0" + hex_str
return hex_str
else:
raise InvalidColor
except InvalidColor:
return "00"
def rgb_to_hex((red, green, blue), upper = True):
r = color_to_hex(red)
g = color_to_hex(green)
b = color_to_hex(blue)
hex_str = "#%s%s%s" % (r, g, b)
if upper:
hex_str = hex_str.upper()
return hex_str
def hex_to_rgb(hex_value):
hex_pattern = re.compile(r"^(#)?(?P<r>[a-f0-9]{2})(?P<g>[a-f0-9]{2})(?P<b>[a-f0-9]{2})$", re.IGNORECASE)
match = hex_pattern.match(hex_value)
HEX_PREFIX = "0x"
BASE = 16
if match:
# could be more DRY-ish, but whatever
r = int(HEX_PREFIX + match.group("r"), BASE)
g = int(HEX_PREFIX + match.group("g"), BASE)
b = int(HEX_PREFIX + match.group("b"), BASE)
else:
raise InvalidColor
return (r, g, b)
#print rgb_to_hex((255, 0, 0))
#print type(hex_to_rgb(rgb_to_hex((107,142,35))))
#print hex_to_rgb("4B0082")
root = Tk()
initial_color_hex = "#0000ff" # blue
final_color_hex = "#44ccff" # light blue
STOP_TIME_MS = 2000
STEP_TIME_MS = 50
"""
def final_color(*args, **kwargs):
root.configure(background = final_color_hex)
"""
def set_color(root, hex_color, *args, **kwargs):
root.configure(background = hex_color)
def linear_fade(root,
hex_start_color,
hex_stop_color,
stop_time_ms = STOP_TIME_MS,
step_time_ms = STEP_TIME_MS,
delay_ms = 0):
root.configure(background = hex_start_color)
(r0, g0, b0) = hex_to_rgb(hex_start_color)
(rf, gf, bf) = hex_to_rgb(hex_stop_color)
delta_r = rf-r0
delta_g = gf-g0
delta_b = bf-b0
#print delta_r, delta_g, delta_b
for time in range(delay_ms, stop_time_ms+1, step_time_ms):
rt = r0 + (delta_r * time // stop_time_ms)
gt = g0 + (delta_g * time // stop_time_ms)
bt = b0 + (delta_b * time // stop_time_ms)
#print (rt, gt, bt)
hex_color_t = rgb_to_hex((rt,gt,bt))
#print time, hex_color_t
root.after(time, set_color(root, hex_color_t))
root.configure(background = initial_color_hex)
#root.after(1000, final_color)
root.geometry("400x400")
linear_fade(root, initial_color_hex, final_color_hex)
root.mainloop()
到目前为止,它似乎是在没有制作窗口的情况下经过for
循环,所以我最终会延迟,然后最终颜色作为背景。
我想我应该去寻找一个更小的工作范例。我试过了:
from Tkinter import *
root = Tk()
initial_color_hex = "#0000ff" # blue
final_color_hex = "#44ccff" # light blue
def set_color(hex_color, *args, **kwargs):
root.configure(background = hex_color)
root.configure(background = initial_color_hex)
root.after(1000, set_color(final_color_hex))
root.geometry("400x400")
root.mainloop()
但我仍然遇到同样的问题。我确实在某个地方找到了某种有用的东西,那就是:
try:
import tkinter
except ImportError:
import Tkinter as tkinter
root = tkinter.Tk()
def grey(*args,**kwargs):
root.configure(background = "grey")
def bthing():
root.configure(background = "red")
root.after(1000, grey)
tkinter.Button(text = "OK", command = bthing).pack()
root.configure(background = "grey")
root.geometry("400x400")
root.mainloop()
但这两个例子之间的关键区别是什么?
答案 0 :(得分:1)
这一行
root.after(time, set_color(root, hex_color_t))
不符合您的想法。此行立即使用参数set_color
和root
评估hex_color_t
函数。然后它会得到结果(在这种情况下偶然为None
)并调度要在time
ms中评估的结果(不用说,评估None
不影响颜色根窗口)。
这就解释了为什么你的窗口会立即改变颜色 - 你的代码会一个接一个地引起所有的颜色变化,然后执行一系列无意义的预定评估。
您可以通过以下方式解决此问题:
def createColorChangeFunction(hcolor):
return lambda:set_color(root, hcolor)
root.after(time, createColorChangeFunction(hex_color_t))
createColorChangeFunction
是必要的,因此各种lambda函数都有自己的本地引用,而不是共享一个。
我测试了这个变化,并且有一个窗口从黑暗到浅蓝色慢慢消失。