label.configure有时为什么工作?

时间:2015-09-01 19:23:11

标签: python tkinter label

我的部分代码如下:

def get_songs():
    label6.configure(text='Wait')
    os.system('/home/norman/my-startups/grabsongs')
    label6.configure(text='Done')

标签不会在第一个.configure()更新,而是在第二个{{1}}。 除非我在第一个之后立即引起故意错误,此时它会被更新,然后程序终止。 系统调用大约需要2分钟才能完成,因此它没有时间显示第一个。

我正在使用Python 2.7.6

有谁知道为什么请?

1 个答案:

答案 0 :(得分:2)

我猜你正在使用Tkinter。如果是这样,正如@albert建议的那样,您想要致电label.update_idletasks()label.update()告诉Tkinter刷新显示。

作为重现问题的一个非常粗略的例子,让我们制作一个程序:

  1. 等一下
  2. 做某事(睡2秒)并将文本更新为"等待"
  3. 显示"完成"之后
  4. 例如:

    import Tkinter as tk
    import time
    
    root = tk.Tk()
    label = tk.Label(root, text='Not waiting yet')
    label.pack()
    
    def do_stuff():
        label.configure(text='Wait')
        time.sleep(2)
        label.configure(text='Done')
    
    label.after(1000, do_stuff)
    tk.mainloop()
    

    请注意"等待"将永远不会被展示。

    要解决此问题,请在初始设置文本后调用update_idletasks()

    import Tkinter as tk
    import time
    
    root = tk.Tk()
    label = tk.Label(root, text='Not waiting yet')
    label.pack()
    
    def do_stuff():
        label.configure(text='Wait')
        label.update_idletasks()
        time.sleep(2)
        label.configure(text='Done')
    
    label.after(1000, do_stuff)
    tk.mainloop()
    

    至于为什么会发生这种情况,实际上是因为Tkinter没有时间更新标签。

    调用configure不会自动强制刷新显示,它只会在下次空闲时排队。因为你立刻调用了一些会停止执行mainloop的东西(调用一个可执行文件并强制python停止直到它完成),Tkinter永远不会有机会处理对标签的更改。

    请注意,虽然gui显示"等待" (当你的进程/睡眠正在运行时)它不会响应调整大小等.Python停止执行,直到另一个进程完成运行。

    要解决此问题,请考虑使用subprocess.Popen(或类似内容)代替os.system。然后,您需要对返回的管道进行perodically轮询以查看子进程是否已完成。

    作为一个例子(我也将其转移到一个类中以防止范围过于混乱):

    import Tkinter as tk
    import subprocess
    
    class Application(object):
        def __init__(self, parent):
            self.parent = parent
            self.label = tk.Label(parent, text='Not waiting yet')
            self.label.pack()
            self.parent.after(1000, self.do_stuff)
    
        def do_stuff(self):
            self.label.configure(text='Wait')
            self._pipe = subprocess.Popen(['/bin/sleep', '2'])
            self.poll()
    
        def poll(self):
            if self._pipe.poll() is None:
                self.label.after(100, self.poll)
            else:
                self.label.configure(text='Done')
    
    root = tk.Tk()
    app = Application(root)
    tk.mainloop()
    

    这里的关键区别是,我们可以在等待外部流程完成时调整窗口大小/移动/交互。另请注意,我们永远不需要调用update_idletasks / update,因为Tkinter现在有空闲时间来更新显示。