每10秒重新绘制一次Python Tkinter标签 [英] Python Tkinter Label redrawing every 10 seconds

查看:315
本文介绍了每10秒重新绘制一次Python Tkinter标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有下面的Python Tkinter代码,该代码每10秒重绘一次标签.我的问题是,对我来说,似乎是一遍又一遍地在旧标签上绘制新标签.因此,最终,几个小时后,将有数百个图纸重叠(至少从我的理解来看).这会占用更多内存还是会引起问题?

I have this following Python Tkinter code which redraw the label every 10 second. My question is , to me it seems like it is drawing the new label over and over again over the old label. So, eventually, after a few hours there will be hundreds of drawing overlapping (at least from what i understand). Will this use more memory or cause problem?

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.但是实际要做的是刷新标签(如表格),按钮和填充物的网格,以与可用的最新数据相匹配.

Here in my example, i am just using a single label.I am aware that i can use textvariable to update the text of the label or even text.config. But what am actually doing is to refresh a grid of label(like a table)+buttons and stuffs to match with the latest data available.

根据我的初学者的理解,如果我将此Draw()函数编写为类,那么只要执行Refresher函数,就可以使用frame.destroy破坏frame.但是我目前拥有的代码是用没有类的函数编写的(我不希望将整个代码重写为类).

From my beginner understanding, if i wrote this Draw() function as class, i can destroy the frame by using frame.destroy whenever i execute Refresher function. But the code i currently have is written in functions without class ( i don't wish to rewrite the whole code into class).

我能想到的另一种选择是在Draw()中将frame声明为全局并使用frame.destroy()(我不愿意这样做,因为如果我有太多帧,这可能会导致名称冲突(我这样做))

The other option i can think of is to declare frame in the Draw() as global and use frame.destroy() ( which i reluctant to do as this could cause name conflict if i have too many frames (which i do))

如果在旧图纸上进行透绘没有引起任何问题(除了我看不到旧图纸),我可以接受.

If overdrawing over the old drawing doesn't cause any problem (except that i can't see the old drawing), i can live with that.

这些都是我的初学者的想法.我应该在重新绘制更新的框架之前销毁框架吗?如果是这样,如果代码结构就像我的示例代码中一样,我应该以哪种方式销毁它?还是改写旧标签就可以了?

These are all just my beginner thoughts. Should i destroy the frame before redraw the updated one? if so, in what way should i destroy it if the code structure is just like in my sample code? Or overdrawing the old label is fine?

编辑

有人提到python tkinter不是线程安全的,我的代码可能会随机失败.

Someone mentioned that python tkinter is not thread safe and my code will likely to fail randomly.

我实际上使用了此链接作为使用threading作为我的解决方案的参考,在那篇文章中我没有发现任何有关线程安全的信息.

I actually took this link as a reference to use threading as my solution and i didn't find anything about thread safety in that post.

我想知道我不应该使用threading的一般情况是什么,我可以使用threading的一般情况是什么?

I am wondering what are the general cases that i should not use threading and what are the general cases i could use threading?

推荐答案

在tkinter中运行函数或更新标签的正确方法是使用

The correct way to run a function or update a label in tkinter is to use the after method. This puts an event on the event queue to be executed at some time in the future. If you have a function that does some work, then puts itself back on the event queue, you have created something that will run forever.

以下是基于您的示例的快速示例:

Here's a quick example based on your example:

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调用一个更新标签的函数,而不必创建新标签.另外,该函数可以安排自己以一定间隔再次被调用.在此示例中,我只是选择了一秒钟,以便更容易看到效果.

There are a lot of things I would change about that program from a coding style point of view, but I wanted to keep it as close to your original question as possible. The point is, you can use after to call a function that updates the label without having to create new labels. Plus, that function can arrange for itself to be called again at some interval. In this example I picked one second just so that the effect is easier to see.

您还问我想知道我不应该使用线程的一般情况是什么,可以使用线程的一般情况是什么?"

You also asked "I am wondering what are the general cases that i should not use threading and what are the general cases i could use threading?"

要直言不讳,如果必须询问有关何时使用线程的问题,则永远不要使用线程.线程化是一项高级技术,它很复杂,而且很容易出错.线程很有可能使您的程序变慢而不是变快.它会产生微妙的后果,例如,如果您执行不安全的线程操作,则程序会神秘地失败.

To put a blunt point on it, you should never use threading if you have to ask a question about when to use threading. Threading is an advanced technique, it is complicated, and it easy to get wrong. It's quite possible for threading to make your program slower rather than faster. It has subtle consequences, such as your programs failing mysteriously if you do things that aren't thread safe.

要更具体地了解您的情况:应避免将线程与tkinter一起使用.您可以可以使用它们,但不能从其他线程访问窗口小部件.如果需要使用窗口小部件做某些事情,则必须将一条指令放入线程安全的队列中,然后在主线程中需要定期检查该队列以查看是否有要处理的指令.如果您搜索它们,此网站上有一些示例.

To be more specific to your situation: you should avoid using threads with tkinter. You can use them, but you can't access widgets from these other threads. If you need to do something with a widget, you must put an instruction in a thread-safe queue, and then in the main thread you need to periodically check that queue to see if there's an instruction to be processed. There are examples of that on this website if you search for them.

如果听起来很复杂,那就对了.对于您编写的大多数GUI,您无需担心.如果您可以处理大型进程并将其分解为100 ms或更短时间内执行的块,则只需要after,就不需要线程.

If all that sounds complicated, it is. For most of the GUIs you write, you won't need to worry about that. If you can take large processes and break them down into chunks that execute in 100 ms or less, you only need after, and never need threads.

这篇关于每10秒重新绘制一次Python Tkinter标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆