繁体   English   中英

使用Tkinter(Python 2.7)随时间变化的颜色偏移

[英]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))

不按照您的想法去做。 该行立即使用参数roothex_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM