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

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

问题描述

我有以下 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() 函数写成类,我可以使用 frame.destroy 销毁 frame每当我执行 Refresher 功能.但是我目前拥有的代码是在没有类的函数中编写的(我不想将整个代码重写为类).

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 中运行函数或更新标签的正确方法是使用 after 方法.这会将事件放在事件队列中,以便在将来的某个时间执行.如果你有一个函数做了一些工作,然后把自己放回事件队列,你就创建了一个永远运行的东西.

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 毫秒或更短的时间内执行的块,那么您只需要 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.

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

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