[英]Time-dependent color shifting with Tkinter (Python 2.7)
我想编写一个程序,在给定的时间段内,将Tkinter窗口的背景从最初的十六进制颜色变为最终的十六进制颜色,同时显示两者之间的某些颜色。 (如果print time, hex_color_t
,请取消注释第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()
但是,这两个示例之间的关键区别是什么?
这条线
root.after(time, set_color(root, hex_color_t))
不按照您的想法去做。 该行立即使用参数root
和hex_color_t
评估set_color
函数。 然后,它需要的结果(这是顺便None
在这种情况下)和时间表中的结果进行评估time
MS(不用说,评估None
不影响根窗口的颜色)。
这就解释了为什么窗口立即更改颜色的原因-您的代码使所有颜色立即相继更改,然后执行了一系列无意义的计划评估。
您可以通过以下方法解决此问题:
def createColorChangeFunction(hcolor):
return lambda:set_color(root, hcolor)
root.after(time, createColorChangeFunction(hex_color_t))
createColorChangeFunction
是必需的,因此各种lambda函数都有自己对十六进制颜色的局部引用,而不是共享一个。
我测试了此更改,并使窗口从深蓝色逐渐淡入淡蓝色。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.