[Tutor] Continuously slower program

Michael P. Reilly arcege@speakeasy.net
Wed, 12 Jun 2002 12:49:32 -0400


On Tue, Jun 11, 2002 at 04:57:28PM -0700, Seiji Funai wrote:
> This is a test for the beginning of a meter that I'm
> writing for a GUI.  The application slows
> continuously.  Does my computer just suck, or is there
> something I can do?  Please let me know.

Your problem is that you continually create new canvas objects inside the
while loop.  You should be creating the objects once, and changing them
as needed.  That was increasing the processing of the Canvas object,
increasing the memory of it, and sucking up CPU time.

Below are the changes to your code.  (Lines starting with "-" are removed,
and lines starting with "+" have been added.)  You want to capture the
canvas id of the red line, then change its coordinates inside the loop with
the "coords" method to the Canvas object.

  -Arcege


  from Tkinter import *
  import math

  class TestMeter:
    def __init__(self, master):
      testMeterFrame = Frame(master)
      testMeterFrame.pack()
      self.count = 0
      self.box = 8, 8, 57, 57
      self.testMeterCanvas = Canvas(testMeterFrame, bg = "gray", width = 65, height = 65)
      self.testMeterCanvas.grid(row = 1, column = 1)
      self.testMeterCanvas.create_oval(2, 2, 63, 63, fill = "black")
      self.testMeterCanvas.create_oval(5, 5, 60, 60, fill = "gray")
      self.testMeterCanvas.create_arc(self.box, start = 0, extent = 180, fill = "white")
      self.testMeterCanvas.create_line(33, 33, 33, 8, fill = "red")
      self.testMeterCanvas.create_text(33, 47, text = "M1")
      self.testMeterCanvas.create_text(10, 38, text = "0")
      self.testMeterCanvas.create_text(55, 38, text = "1")
      self.startButton = Button(testMeterFrame, text = "Start", command = self.start)
      self.startButton.grid(row = 2, column = 1, sticky = W+E+N+S)

    def start(self):
      self.testMeterCanvas.create_arc(self.box, start = 0, extent = 180, fill = "white")
+     self.x = 25 * math.sin(self.count) + 33
+     self.y = -25 * math.fabs(math.cos(self.count)) + 33
+     self.c = self.testMeterCanvas.create_line(33, 33, self.x, self.y, fill="red")

      while 1:
        self.count = self.count + .1
        if self.count == 1000:
          self.count = 0
-       self.testMeterCanvas.create_arc(self.box, start = 0, extent = 180, fill = "white")
        self.x = 25 * math.sin(self.count) + 33
        self.y = -25 * math.fabs(math.cos(self.count)) + 33
-       self.testMeterCanvas.create_line(33, 33, self.x, self.y, fill = "red")
+       self.testMeterCanvas.coords(self.c, 33, 33, self.x, self.y)
        root.update()

    def stop(self):
      self.testMeterCanvas.create_arc(self.box, start = 0, extent = 180, fill = "white")
      self.testMeterCanvas.create_line(33, 33, 33, 8, fill = "red")

  root = Tk()
  testMeter = TestMeter(root)
  root.mainloop()