1

I am prototyping a program with the built-in Python GUI Tkinter, and am having some trouble when I attempt to update multiple labels at the same time. The GUI can handle it for a few refreshes, but after 10 seconds or so it will freeze. I need all of the labels to update at very close to the same time, as each label displays a different piece of sensor data.

Right now, I am using the random module to constantly generate numbers in place of the actual data. There will be 10 or so labels doing this at the same time, and I want to make sure tkinter can handle it. The labels will update every fraction of a second as well ( around 200 milliseconds). I'm using python 3.3 on windows.

I have read about some options, but I'm inexperienced with tkinter. Links: Here. And Here.

Should I consider multithreading? Multiprocessing? I have no experience with either, but I am willing to learn either if it means solving this.

Is what I'm trying to do even possible with tkinter? Should I be using pygame or another GUI? What am I missing here?

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()
Community
  • 1
  • 1
user2740614
  • 285
  • 3
  • 17
  • Tkinter can easily handle updating 10 labels. You probably have to have thousands before you see a performance issue (not counting any overhead required to compute the new values) – Bryan Oakley Sep 02 '13 at 20:05

1 Answers1

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.

rlms
  • 10,650
  • 8
  • 44
  • 61