简体   繁体   English

使用`after`时无法“闪烁” /更改tkinter小部件的颜色

[英]Fail to “blink”/ change color of tkinter widget when using `after`

I'm trying to simulate a blink of a label widget by changing its color in this manner: 我试图通过以这种方式更改其颜色来模拟标签小部件的闪烁:

a) change to color #1, pause 1 sec, a)更改为颜色1,暂停1秒,

b) change to color #2, pause 1 sec, b)更改为颜色2,暂停1秒钟,

c) loop again using tk.after to rerun this procedure. c)使用tk.after再次循环以重新运行此过程。

But the result is a constant color, #2. 但是结果是恒定的颜色#2。

self.blink_status is an index telling communication status is OK, and equals to 1 . self.blink_status是一个指示通信状态为OK的索引,等于1 of course code was tested with a constant value self.blink_status=1 当然,代码已使用常量self.blink_status=1进行了测试

def blink_tx(self):
    if self.blink_status == 1:
        self.tx_label["bg"] = 'green'
        self.tx_value.set('Tx')
        sleep(1)
        self.tx_label["bg"] = 'blue'
        sleep(1)
    elif self.blink_status == 0:
        self.tx_label["bg"] = 'red'
        self.tx_value.set('*')
        sleep(2)
        self.tx_label["bg"] = 'orange'
    else:
        self.tx_label["bg"] = 'red'
        self.tx_value.set('x')
        sleep(2)

    self.status_frame.after(3500, self.blink_tx)

the way self.tx_label and self.tx_value are defined : self.tx_labelself.tx_value的定义方式:

self.tx_label = tk.Label(self.status_frame, textvariable=self.tx_value, relief=tk.GROOVE, width=2)
self.tx_label.grid(row=0, column=4, sticky=tk.E)

You cannot use sleep() inside of a tkinter instance. 您不能在tkinter实例内部使用sleep() Tkinter is a single thread application and when you tell it to sleep everything in the event list is put on hold/freezes. Tkinter是一个单线程应用程序,当您告诉它进入睡眠状态时,事件列表中的所有内容都将保持/冻结状态。 You need to use after() for any delays in your code. 您需要使用after()来延迟代码。 The after() method is specifically meant to manage delays in tkinter. after()方法专门用于管理tkinter中的延迟。

Because in your example it appears you are running 2 separate delays my example will provide both delays. 因为在您的示例中您似乎正在运行2个单独的延迟,所以我的示例将同时提供这两个延迟。

Here is an exampled composed from the code you provided. 这是由您提供的代码组成的示例。 We can set all the delays we need buy provided a 2nd function. 我们可以设置第二功能来设置所有需要购买的延迟时间。 I have added a random number generator to the code to illustrate a continuous change of the colors. 我在代码中添加了一个随机数生成器,以说明颜色的连续变化。

import tkinter as tk
import random


class MainApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)

        self.tx_value = tk.StringVar()
        self.tx_value.set("test")
        self.blink_status = 1

        self.tx_label = tk.Label(self, textvariable=self.tx_value, relief=tk.GROOVE, width=4, height=2)
        self.tx_label.grid(row=0, column=4, sticky=tk.E)
        self.blink_tx()

    def blink_tx_step_2(self, color=None):
        if color != None:
            self.tx_label["bg"] = color
        self.after(3500, self.blink_tx)

    def blink_tx(self):
        if self.blink_status == 1:
            self.tx_label["bg"] = 'green'
            self.tx_value.set('Tx')
            self.blink_status = random.randint(0, 2)
            self.after(1000, self.blink_tx_step_2, 'blue')
        elif self.blink_status == 0:
            self.tx_label["bg"] = 'red'
            self.tx_value.set('*')
            self.blink_status = random.randint(0, 2)
            self.after(2000, self.blink_tx_step_2, 'orange')
        else:
            self.tx_label["bg"] = 'red'
            self.tx_value.set('x')
            self.blink_status = random.randint(0, 2)
            self.after(2000, self.blink_tx_step_2)


if __name__ == '__main__':
    app = MainApp()
    app.mainloop()

time.sleep() is blocking your GUI updates; time.sleep()阻止您的GUI更新; do not use it with a GUI. 不要将其与GUI一起使用。 Use root.after instead. 请改用root.after

The following label will start blinking when you click on the GUI: 当您单击GUI时,以下标签将开始闪烁:
You can adapt it to your own code that was not provided. 您可以将其调整为未提供的自己的代码。

import tkinter as tk


class BlinkerLabel(tk.Label):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.status = 1

    def blink(self, event):
        if self.status == 1:
            self["bg"] = 'green'
        elif self.status == 0:
            self["bg"] = 'red'

        self.status = (self.status + 1) % 2
        self.after(3500, self.blink, 'dummy_event')  # <-- this creates the 'delay' between blinks


if __name__ == '__main__':

    root = tk.Tk()
    lbl = BlinkerLabel(root, text='I blink!')
    lbl.pack()

    root.bind('<Button-1>', lbl.blink)

    root.mainloop()

Thanks for @Mike-SMT and @Reblochon Masque for helping. 感谢@ Mike-SMT和@Reblochon Masque的帮助。 TNX ALOT TNX很多

My code fix: 我的代码修复:

def blink_tx(self):
    def blink_1(color1, color2, txt):
        self.tx_label["bg"] = color1
        self.tx_value.set(txt)
        self.after(t_blink, blink_2, color2)

    def blink_2(color):
        self.tx_label["bg"] = color
        self.after(t_blink, self.blink_tx)

    t_blink = 2500
    if self.blink_status == 1:
        blink_1('green', 'orange', 'Tx')
    elif self.blink_status == 0:
        blink_1('red', 'yellow', '*')
    else:
        blink_1('red', 'red', 'X')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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