label.configure 有时有效,为什么?
label.configure works sometimes why?
我的部分代码如下:
def get_songs():
label6.configure(text='Wait')
os.system('/home/norman/my-startups/grabsongs')
label6.configure(text='Done')
标签在第一个 .configure()
时未更新,但在第二个时更新。
除非我在第一个错误之后立即引起故意错误,此时它被更新,然后程序终止。
系统调用大约需要2分钟完成,所以不是没有时间显示第一个。
我正在使用 Python 2.7.6
有谁知道为什么吗?
我猜你正在使用 Tkinter
。如果是这样,正如@albert 刚刚建议的那样,您需要调用 label.update_idletasks()
或 label.update()
来告诉 Tkinter 刷新显示。
作为重现问题的一个非常粗略的例子,让我们编写一个程序:
- 等待 1 秒
- 做点什么(休眠 2 秒)并将文本更新为 "wait"
- 之后显示"done"
例如:
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()
请注意,"Wait" 永远不会显示。
要解决这个问题,让我们在初始设置文本后调用 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 显示 "Wait"(而您的 process/sleep 是 运行)时,它不会响应调整大小等。Python 已停止执行,直到另一个进程完成 运行.
要解决这个问题,请考虑使用 subprocess.Popen
(或类似的东西)而不是 os.system
。然后您需要定期轮询返回的管道以查看子进程是否已完成。
举个例子(我也将其移至 class 以防止范围界定过于混乱):
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()
这里的主要区别在于我们可以在等待外部进程完成时使用 resize/move/interact 和 window。另请注意,我们从来不需要调用 update_idletasks
/update
,因为 Tkinter 现在确实有空闲时间来更新显示。
我的部分代码如下:
def get_songs():
label6.configure(text='Wait')
os.system('/home/norman/my-startups/grabsongs')
label6.configure(text='Done')
标签在第一个 .configure()
时未更新,但在第二个时更新。
除非我在第一个错误之后立即引起故意错误,此时它被更新,然后程序终止。
系统调用大约需要2分钟完成,所以不是没有时间显示第一个。
我正在使用 Python 2.7.6
有谁知道为什么吗?
我猜你正在使用 Tkinter
。如果是这样,正如@albert 刚刚建议的那样,您需要调用 label.update_idletasks()
或 label.update()
来告诉 Tkinter 刷新显示。
作为重现问题的一个非常粗略的例子,让我们编写一个程序:
- 等待 1 秒
- 做点什么(休眠 2 秒)并将文本更新为 "wait"
- 之后显示"done"
例如:
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()
请注意,"Wait" 永远不会显示。
要解决这个问题,让我们在初始设置文本后调用 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 显示 "Wait"(而您的 process/sleep 是 运行)时,它不会响应调整大小等。Python 已停止执行,直到另一个进程完成 运行.
要解决这个问题,请考虑使用 subprocess.Popen
(或类似的东西)而不是 os.system
。然后您需要定期轮询返回的管道以查看子进程是否已完成。
举个例子(我也将其移至 class 以防止范围界定过于混乱):
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()
这里的主要区别在于我们可以在等待外部进程完成时使用 resize/move/interact 和 window。另请注意,我们从来不需要调用 update_idletasks
/update
,因为 Tkinter 现在确实有空闲时间来更新显示。