首页 > 解决方案 > 在 Tkinter 上更改主循环内显示的图像?

问题描述

我正在尝试制作一个程序来显示单色全屏。这个想法是在一个大屏幕上使用它来创造房间里的环境,屏幕在一定时间后从一种颜色变成另一种颜色。

显示彩色全屏不是问题,但我怎样才能顺利地改变所说的颜色?

对于全屏显示,我使用了与屏幕大小相同的 Tkinter 窗口:某种颜色imagesprite = canvas.create_image(w/2, h/2, image=image)在哪里。image但是要更改颜色,我需要使用销毁窗口root.after(2000, root.destroy)然后创建一个新窗口。这并不顺利,因为可以在短时间内看到桌面。

如何随时随地更改 Tkinter 窗口中显示的图像,或者如何关闭一个窗口并顺利打开另一个窗口?

标签: pythontkinterdisplay

解决方案


您可以选择为 Canvas 对象设置背景,而不是使用图像。这是具有单一颜色背景的最少代码。

from tkinter import Tk, Canvas
root = Tk()
root.attributes("-fullscreen",True)#Makes the window fullscreen
canvas = Canvas(root, width=root.winfo_width(),height=root.winfo_height(), background="red") #Makes a canvas with a red coloured background
#The width and height of the Canvas are taken from the root object
canvas.pack()
root.mainloop()

从这里开始,而不是不断地删除窗口,可以只更改 Tkinter 小部件的属性。这是使用 config 方法完成的。

canvas.config(background="green")

tkinter 的一个优点是你可以给它一个颜色的十六进制代码,它会使用它来绘制。它需要采用如下格式的字符串: "#RRGGBB"其中每个组是从 0 到 FF 的十六进制数。

考虑到这一点,您可以增加每帧的十六进制数,或者增加两种颜色之间所需的帧数。要获得良好的过渡效果,您可能需要使用色相、饱和度、值 (HSV) 颜色,并且只更改色相值。

您可以将 HSV 存储在列表中:

hsv = [0,0.7,0.7]

要进行转换,您首先要转换为 0 到 255 RGB,然后再转换为十六进制。

import colorsys
rgb = colorsys.hsv_to_rgb(*hsv) #Uses list unpacking to give it as arguments

接下来,您使用 rgb 并将其转换为 Hexcode 形式。

def getHexCode(rgb):
    r = hex(int(rgb[0]*255))[2:] #converts to hexadecimal
    #With the hex() function, it returns a number in "0xFE" format (0x representing hex).
    #To ignore this, we can take the substring using [2:]
    if len(r) < 2: #If the value is a 1-digit number, then we want to add a zero at the front for hexcode form
        r = "0"+r
    g = hex(int(rgb[1]*255))[2:]
    if len(g) < 2:
        g = "0"+g
    b = hex(int(rgb[2]*255))[2:]
    if len(b) < 2:
        b = "0"+b

    return "#" + r + g + b

最后,我们实际上调用了change方法。

changeSpeed = 200
def changeColor():
    rgb = colorsys.hsv_to_rgb(*hsv)
    hexCode = getHexCode(rgb)
    canvas.config(background = hexCode)
    hsv[0]+=0.01
    root.after(changeSpeed,changeColor)

root.after(changeSpeed, changeColor)

(已编辑)以前存在问题的两件事是root.winfo_width()and root.winfo_height(),以及全屏显示边框。

为了解决第一个问题,我们必须以某种方式更新根对象,因为默认情况下它是 1x1。我们可以做的是创建Canvas对象然后更新它。它看起来像这样:

canvas = Canvas(root, width=100,height=100, background="white",highlightthickness=0) #Makes a canvas with a white coloured background
canvas.pack()
canvas.update()
canvas.config(width = root.winfo_width(), height = root.winfo_height())

第二个问题也可以通过使画布对象具有特定属性来解决,highlightthickness=0。如果您注意到,画布对象初始化现在是:

canvas = Canvas(root, width=100,height=100, background="white",highlightthickness=0)

我认为有用的另一件事是按钮是否关闭程序。我使用以下方法将“Escape”键绑定到关闭:

def quit(event):
    root.destroy()

root.bind("<Escape>", quit)

作为一个完整的程序,它看起来像这样:

import colorsys
from tkinter import Tk, Canvas

hsv = [0,1,0.8]
changeSpeed = 200

root = Tk()
root.attributes("-fullscreen",True)
canvas = Canvas(root, width=100,height=100, background="white",highlightthickness=0) #Makes a canvas with a white coloured background
canvas.pack()
canvas.update()
canvas.config(width = root.winfo_width(), height = root.winfo_height())


def getHexCode(rgb):
    r = hex(int(rgb[0]*255))[2:]
    if len(r) < 2:
        r = "0"+r
    g = hex(int(rgb[1]*255))[2:]
    if len(g) < 2:
        g = "0"+g
    b = hex(int(rgb[2]*255))[2:]
    if len(b) < 2:
        b = "0"+b

    return "#" + r + g + b

def changeColor():
    rgb = colorsys.hsv_to_rgb(*hsv)
    hexCode = getHexCode(rgb)
    canvas.config(background = hexCode)
    hsv[0]+=0.01
    root.after(changeSpeed,changeColor)

def quit(event):
    root.destroy()

root.after(changeSpeed, changeColor)
root.bind("<Escape>", quit)

root.mainloop()

您可以在其中更改的一些变量是 changeSpeed、原始 hsv 列表以及每次增加的色调中添加的 0.01


推荐阅读