我有以下Python
Tkinter代码,该代码每10秒重绘一次标签。我的问题是,对我而言,似乎是一遍又一遍地在旧标签上绘制新标签。因此,最终,几个小时后,将有数百个图纸重叠(至少从我的理解来看)。这会占用更多内存还是会引起问题?
import Tkinter as tk
import threading
def Draw():
frame=tk.Frame(root,width=100,height=100,relief='solid',bd=1)
frame.place(x=10,y=10)
text=tk.Label(frame,text='HELLO')
text.pack()
def Refresher():
print 'refreshing'
Draw()
threading.Timer(10, Refresher).start()
root=tk.Tk()
Refresher()
root.mainloop()
在我的示例中,我仅使用一个标签。我知道可以textvariable
用来更新标签甚至是文本text.config
。但是实际要做的是刷新标签(如表格),按钮和填充物的网格,以与可用的最新数据相匹配。
从我了解的初学者,如果我写了这个Draw()
功能类,我可以摧毁frame
利用frame.destroy
每当我执行Refresher
功能。但是我目前拥有的代码是在没有类的函数中编写的(我不希望将整个代码重写为类)。
我能想到的另一种选择是将frame
in声明Draw()
为global并使用frame.destroy()
(我不愿意这样做,因为如果我有太多帧(这样做),可能会导致名称冲突)
如果在旧图纸上进行透绘不会引起任何问题(除了我看不到旧图纸),我可以接受。
这些都是我的初学者的想法。我应该在重新绘制更新的框架之前销毁框架吗?如果是这样,如果代码结构就像我的示例代码一样,我应该以哪种方式销毁它?还是透支旧标签就可以了?
编辑
有人提到python tkinter不是线程安全的,我的代码可能会随机失败。
我实际上将此链接作为threading
解决方案的参考,但在那篇文章中我没有找到有关线程安全的任何信息。
我想知道我不应该使用threading
哪些一般情况,我可以使用哪些一般情况threading
?
在tkinter中运行函数或更新标签的正确方法是使用after方法。这会将事件放在事件队列中,以在将来的某个时间执行。如果您有一个可以完成某些工作的函数,然后将其放回到事件队列中,那么您已经创建了可以永久运行的函数。
这是一个基于您的示例的快速示例:
import Tkinter as tk
import time
def Draw():
global text
frame=tk.Frame(root,width=100,height=100,relief='solid',bd=1)
frame.place(x=10,y=10)
text=tk.Label(frame,text='HELLO')
text.pack()
def Refresher():
global text
text.configure(text=time.asctime())
root.after(1000, Refresher) # every second...
root=tk.Tk()
Draw()
Refresher()
root.mainloop()
从编码风格的角度来看,我会对该程序进行很多更改,但我希望使其尽可能地接近您的原始问题。关键是,您可以after
用来调用一个更新标签的函数,而不必创建新标签。另外,该函数可以安排自己以一定间隔再次被调用。在此html" target="_blank">示例中,我只是选择了一秒钟,以便更容易看到效果。
您还问:“我想知道我不应该使用线程的一般情况是什么,可以使用线程的一般情况是什么?”
为了直言不讳,如果您必须询问有关何时使用线程的问题,则永远不要使用线程。线程化是一项高级技术,它很复杂,而且很容易出错。线程很有可能使程序变慢而不是变慢。它具有微妙的后果,例如,如果您执行不安全线程的操作,则程序会神秘地失败。
要更具体地了解您的情况:您应该避免在tkinter中使用线程。您 可以
使用它们,但不能从其他线程访问窗口小部件。如果需要对窗口小部件进行某些操作,则必须将指令放入线程安全的队列中,然后在主线程中需要定期检查该队列以查看是否有要处理的指令。如果您搜索它们,此网站上有一些示例。
如果这听起来很复杂,那就是。对于您编写的大多数GUI,您无需担心。如果您可以处理大型流程并将其分解为100
ms或更短时间内执行的块,则只需要after
,就不需要线程。
问题内容: 我有一个C#Windows窗体,其中包含几个文本框和按钮。它还具有显示sql表的datagrid视图。我创建了一个刷新按钮,使我可以刷新表,以便可以看到表中的更新项。我想知道有没有办法自行刷新表。就像每10秒一次,或者代替表格,也许每10秒就会自动加载或刷新整个表格吗? 问题答案: 使用Timer控件,它调用了UI线程,并且可以通过表单设计器使用该控件。
问题内容: 我想在单击按钮时从GUIinput获取数据,我编写此代码以获取数据,然后进入无限循环 问题答案: 我想单击按钮时从GUIinput获取数据 您正在上使用,这将阻止GUI响应事件,直到循环完成为止。 不要在EDT上使用Thread.sleep(…)! 有两种常见的解决方案: 使用Swing计时器每10秒安排一次事件。 使用单独的线程。然后,在此线程中,可以使用Thread.sleep()
我想每10秒执行一段代码。我在这个论坛上找到了一个例子,但我的实现有一些问题。 我得到这个错误,指向:
问题内容: 当图表第一次使用初始默认Ajax答复加载时,它可以正常工作。如果我添加console.log(chart_data),我会看到默认数据,然后在提交后我会看到新数据。唯一的问题是图表不会再次绘制。我知道drawChart函数不会第二次运行,我只是不知道为什么。我假设是的话,图表将重绘。抱歉,答案很明显。我对jQuery / Ajax非常陌生。 任何帮助,将不胜感激。谢谢! 问题答案: 您
问题内容: 我正在将一种布局转换为html; 一旦我在code / html / css中进行了更改,每次必须按F5。是否有任何简单的javascript / jQuery解决方案?即,在添加脚本之后,每5秒(或其他特定时间)重新加载整个页面。 问题答案: 如果必须在脚本中使用setTimeout,例如:
问题内容: 目前,每35秒更改一次位置并移动10米的距离后,我就会在上绘制一个。 因此,我在位置更改(移动35秒和10米)后立即实现了此功能,我正在绘制。 问题陈述:- 。有时我的应用程序被挂起?可能是因为我的代码在下面的编写方式中效率不高? 基本上,我只需要在每移动35秒和10米的距离后在当前位置绘制一个圆圈。 我的代码有问题吗?任何想法,例如我应该如何进一步改善它,以使其顺利运行。 这是我在M