0

我想编写一个程序,在给定的时间段内将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()

但这两个例子之间的关键区别是什么?

4

1 回答 1

1

这条线

root.after(time, set_color(root, hex_color_t))

不做你认为它做的事。此行立即使用参数和评估set_color函数。然后它获取结果(在这种情况下是偶然的)并安排在ms 内评估结果(不用说,评估不会影响根窗口的颜色)。 roothex_color_tNonetimeNone

这解释了为什么您的窗口会立即改变颜色 - 您的代码会立即导致所有颜色变化,然后执行一系列无意义的预定评估。

您可以通过执行以下操作来解决此问题:

def createColorChangeFunction(hcolor):
    return lambda:set_color(root, hcolor)
root.after(time, createColorChangeFunction(hex_color_t))

createColorChangeFunction是必要的,因此各种 lambda 函数都有自己对十六进制颜色的本地引用,而不是共享一个。

我测试了这种变化,并得到一个窗口从深蓝色慢慢褪色到浅蓝色。

于 2013-10-21T22:37:09.287 回答