1

我正在使用内置 Python GUI Tkinter 对程序进行原型设计,当我尝试同时更新多个标签时遇到了一些麻烦。GUI 可以处理几次刷新,但 10 秒左右后它会冻结。我需要所有标签几乎同时更新,因为每个标签显示不同的传感器数据。

现在,我正在使用该random模块不断生成数字来代替实际数据。将有 10 个左右的标签同时执行此操作,我想确保 tkinter 可以处理它。标签也会每隔一秒更新一次(大约 200 毫秒)。我在 Windows 上使用 python 3.3。

我已经阅读了一些选项,但我对 tkinter 没有经验。链接: 这里。 和这里。

我应该考虑多线程吗?多处理?我都没有经验,但如果这意味着解决这个问题,我愿意学习。

我正在尝试做的甚至可能tkinter吗?我应该使用pygame还是其他 GUI?我在这里想念什么?

import random
from tkinter import *

class Application(Frame):
    """The GUI window"""
    def __init__(self, master):
        """Setup the Frame"""
        super(Application, self).__init__(master)
        self.grid() 
        self.setupWidgets()
        self.update()

    def setupWidgets(self):
        """Setup widgets for use in GUI"""

        #setup data readings
        self.data_lbl_txt = "Data Readings"
        self.data_lbl = Label(self, text = self.data_lbl_txt)
        self.data_lbl.grid(row = 0, column = 1, columnspan = 2, sticky = E)


        #setup first data piece
        self.data1_txt = "First piece of data:"
        self.data1_lbl = Label(self, text = self.data1_txt)
        self.data1_lbl.grid(row = 1, column = 1, sticky = W)

        self.data1 = StringVar()
        self.data1_Var = Label(self, textvariable = self.data1)
        self.data1_Var.grid(row = 1, column = 2, sticky = W)

        #setup second data piece
        self.data2_txt = "Second piece of data:"
        self.data2_lbl = Label(self, text = self.data2_txt)
        self.data2_lbl.grid(row = 2, column = 1, sticky = W)

        self.data2 = StringVar()
        self.data2_Var = Label(self, textvariable = self.data2)
        self.data2_Var.grid(row = 2, column = 2, sticky = W)


    def update(self):
        self.data1.set(random.randint(1,10))
        self.data1_Var.after(200, self.update)

        self.data2.set(random.randint(1,10))
        self.data2_Var.after(200, self.update)



root = Tk()
root.title("Data Output")
root.geometry("600x250")
window = Application(root)


window.mainloop()
4

1 回答 1

3

I believe here you have inadvertently created a fork bomb in the update method.

This code:

def update(self):
    self.data1.set(random.randint(1,10))
    self.data1_Var.after(200, self.update)

    self.data2.set(random.randint(1,10))
    self.data2_Var.after(200, self.update)

means that each time the method is called, it is called twice again (or rather will be, 200 milliseconds in the future, as you have .after(200, self.update) twice.

This means instead of this:

update is called 1x
200 millisecond gap
update is called 1x
200 millisecond gap
update is called 1x
200 millisecond gap
update is called 1x
200 millisecond gap
update is called 1x
200 millisecond gap...

you have this:

update is called 1x
200 millisecond gap
update is called 2x
200 millisecond gap
update is called 4x
200 millisecond gap
update is called 8x
200 millisecond gap
update is called 16x
200 millisecond gap...

It will freeze after around 10 seconds (or 10,000 milliseconds) because it is trying to call 2^50 (or 1125899906842624) update functions at once!

I think (it's been some time since I've used Tkinter) the solution to this is to do root.after in that function instead. Alternatively, you could make several different update functions, one for each label, each of which only calls after once.

于 2013-09-02T18:40:40.910 回答