Tkinter 进度条/窗口移动时没有响应
我从这里借用了一个进度条,我想用全局变量来调整我的程序中的工作。以下是供参考的代码:
import Tkinter
class Meter(Tkinter.Frame):
def __init__(self, master, width=300, height=20, bg='white', fillcolor='orchid1',\
value=0.0, text=None, font=None, textcolor='black', *args, **kw):
Tkinter.Frame.__init__(self, master, bg=bg, width=width, height=height, *args, **kw)
self._value = value
self._canv = Tkinter.Canvas(self, bg=self['bg'], width=self['width'], height=self['height'],\
highlightthickness=0, relief='flat', bd=0)
self._canv.pack(fill='both', expand=1)
self._rect = self._canv.create_rectangle(0, 0, 0, self._canv.winfo_reqheight(), fill=fillcolor,\
width=0)
self._text = self._canv.create_text(self._canv.winfo_reqwidth()/2, self._canv.winfo_reqheight()/2,\
text='', fill=textcolor)
if font:
self._canv.itemconfigure(self._text, font=font)
self.set(value, text)
self.bind('<Configure>', self._update_coords)
def _update_coords(self, event):
'''Updates the position of the text and rectangle inside the canvas when the size of
the widget gets changed.'''
# looks like we have to call update_idletasks() twice to make sure
# to get the results we expect
self._canv.update_idletasks()
self._canv.coords(self._text, self._canv.winfo_width()/2, self._canv.winfo_height()/2)
self._canv.coords(self._rect, 0, 0, self._canv.winfo_width()*self._value, self._canv.winfo_height())
self._canv.update_idletasks()
def get(self):
return self._value, self._canv.itemcget(self._text, 'text')
def set(self, value=0.0, text=None):
#make the value failsafe:
if value < 0.0:
value = 0.0
elif value > 1.0:
value = 1.0
self._value = value
if text == None:
#if no text is specified use the default percentage string:
text = str(int(round(100 * value))) + ' %'
self._canv.coords(self._rect, 0, 0, self._canv.winfo_width()*value, self._canv.winfo_height())
self._canv.itemconfigure(self._text, text=text)
self._canv.update_idletasks()
##-------------demo code--------------------------------------------##
def _demo(meter, value):
meter.set(value)
if value < 1.0:
value = value + 0.005
meter.after(50, lambda: _demo(meter, value))
else:
meter.set(value, 'Demo successfully finished')
if __name__ == '__main__':
root = Tkinter.Tk(className='meter demo')
m = Meter(root, relief='ridge', bd=3)
m.pack(fill='x')
m.set(0.0, 'Starting demo...')
m.after(1000, lambda: _demo(m, 0.0))
root.mainloop()
此代码和演示工作得很好,但是当我进行以下更改以便我可以测试如何将其实施到我的代码中时,每当我移动或激活进度窗口时,进度窗口就会变得无响应并变为空白另一个窗口。
##-------------demo code--------------------------------------------##
def some_fct(m):
global count
i = 0
while i < 5:
count = count + 1
sleep(2)
m.set(float(count) / total)
i = i + 1
def other_fct(m):
global count
i = 0
while i < 5:
count = count + 1
sleep(2)
m.set(float(count) / total)
i = i + 1
if __name__ == '__main__':
global count
global total
count = 0
total = 10
root = Tkinter.Tk(className='meter demo')
m = Meter(root, relief='ridge', bd=3)
m.pack(fill='x')
m.set(0.0, 'Starting meter')
some_fct(m)
other_fct(m)
root.mainloop()
知道这里发生了什么以及为什么它变得没有响应吗?它与所使用的全局变量有什么关系吗?当它不移动时,它似乎工作“正常”,但它绝对不一样。
I have borrowed a progress bar from here that I would like to adapt work in my program with global variables. Here is the code for reference:
import Tkinter
class Meter(Tkinter.Frame):
def __init__(self, master, width=300, height=20, bg='white', fillcolor='orchid1',\
value=0.0, text=None, font=None, textcolor='black', *args, **kw):
Tkinter.Frame.__init__(self, master, bg=bg, width=width, height=height, *args, **kw)
self._value = value
self._canv = Tkinter.Canvas(self, bg=self['bg'], width=self['width'], height=self['height'],\
highlightthickness=0, relief='flat', bd=0)
self._canv.pack(fill='both', expand=1)
self._rect = self._canv.create_rectangle(0, 0, 0, self._canv.winfo_reqheight(), fill=fillcolor,\
width=0)
self._text = self._canv.create_text(self._canv.winfo_reqwidth()/2, self._canv.winfo_reqheight()/2,\
text='', fill=textcolor)
if font:
self._canv.itemconfigure(self._text, font=font)
self.set(value, text)
self.bind('<Configure>', self._update_coords)
def _update_coords(self, event):
'''Updates the position of the text and rectangle inside the canvas when the size of
the widget gets changed.'''
# looks like we have to call update_idletasks() twice to make sure
# to get the results we expect
self._canv.update_idletasks()
self._canv.coords(self._text, self._canv.winfo_width()/2, self._canv.winfo_height()/2)
self._canv.coords(self._rect, 0, 0, self._canv.winfo_width()*self._value, self._canv.winfo_height())
self._canv.update_idletasks()
def get(self):
return self._value, self._canv.itemcget(self._text, 'text')
def set(self, value=0.0, text=None):
#make the value failsafe:
if value < 0.0:
value = 0.0
elif value > 1.0:
value = 1.0
self._value = value
if text == None:
#if no text is specified use the default percentage string:
text = str(int(round(100 * value))) + ' %'
self._canv.coords(self._rect, 0, 0, self._canv.winfo_width()*value, self._canv.winfo_height())
self._canv.itemconfigure(self._text, text=text)
self._canv.update_idletasks()
##-------------demo code--------------------------------------------##
def _demo(meter, value):
meter.set(value)
if value < 1.0:
value = value + 0.005
meter.after(50, lambda: _demo(meter, value))
else:
meter.set(value, 'Demo successfully finished')
if __name__ == '__main__':
root = Tkinter.Tk(className='meter demo')
m = Meter(root, relief='ridge', bd=3)
m.pack(fill='x')
m.set(0.0, 'Starting demo...')
m.after(1000, lambda: _demo(m, 0.0))
root.mainloop()
This code and demo work great, but when I make the following changes so I can test how I would want to impliment it into my code, the progress window becomes unresponsive and turns blank whenever I move it or activate another window.
##-------------demo code--------------------------------------------##
def some_fct(m):
global count
i = 0
while i < 5:
count = count + 1
sleep(2)
m.set(float(count) / total)
i = i + 1
def other_fct(m):
global count
i = 0
while i < 5:
count = count + 1
sleep(2)
m.set(float(count) / total)
i = i + 1
if __name__ == '__main__':
global count
global total
count = 0
total = 10
root = Tkinter.Tk(className='meter demo')
m = Meter(root, relief='ridge', bd=3)
m.pack(fill='x')
m.set(0.0, 'Starting meter')
some_fct(m)
other_fct(m)
root.mainloop()
Any idea what is going on here and why it becomes unresponsive? Does it have anything to do with the global variable being used? It seems to work "ok" when it's not moved, but it's definitely not the same.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
some_fct
和other_fct
均休眠 10 秒,因此应用在启动时将至少有 20 秒无响应,因为这些休眠均发生在mainloop< 之前/code> 被调用。您是说即使在这 20 秒之后应用程序也没有响应,还是您在问为什么它在前 20 秒没有响应?
Tkinter 是单线程的,这意味着任何时候您进入睡眠状态,它都无法在睡眠期间为事件提供服务。正是这种事件服务定义了“响应性”。
some_fct
andother_fct
both sleep for 10 seconds each, so the app will be unresponsive for at least 20 seconds when it starts up since those sleeps all happen beforemainloop
is called. Are you saying that even after those 20 seconds the app is unresponsive, or are you asking why it's unresponsive for the first 20 seconds?Tkinter is single threaded, which means that any time you put in a sleep it's not going to be able to service events for the duration of the sleep. It is this servicing of events that defines "responsiveness".
这是我用来获得我想要的东西的代码:
Here is the code I used to get what I wanted: