Mark Richman
Mark Richman

Reputation: 29710

tkinter is very slow - how to speed it up or use a different library?

I am generating 2D morphogenic plots using tkinter. I find it incredibly slow. For example, this script takes almost 10 seconds on my 8-core Xeon:

#!/usr/bin/env python3

import random
import tkinter as tk

A = 3.419384662527591
B = 2.0158889752347022
C = 19.479697084985673
D = 61.006212908774614
F = 1.3449991745874286
G = 1.9590223710983992
H = 5.129501734860241
WIDTH = 800
HEIGHT = 600


class Morphogenic(tk.Frame):

    def __init__(self, root):
        tk.Frame.__init__(self, root)
        self.canvas = tk.Canvas(width=WIDTH, height=HEIGHT, borderwidth=1)
        self.canvas.pack(side="top", fill="both", expand=True)

    def rand(self):
        A = 3 + random.random() * 10
        B = 1 + random.random() * 5
        C = 1 + random.random() * 20
        D = 1 + random.random() * 200
        F = 1 + random.random() * 2
        G = 1 + random.random() * 20
        H = 1 + random.random() * 20

    def draw(self):
        points = [0] * HEIGHT
        points_space = [0] * HEIGHT
        points_energy = [0] * HEIGHT
        w = WIDTH
        h = HEIGHT
        min_x = 0

        last_x = 0
        last_y = 0

        while min_x < w:
            min_x = w
            lrand = 0

            for y in range(1, h):
                points_space[y] = points_space[y] + \
                    (points_space[y - 1] - points_space[y]) / F

            for y in range(0, h):
                lrand = lrand + (random.random() - 0.5) / C
                new_point = points[y] + points_space[y] + lrand
                points_space[y] = (new_point - points[y]) + \
                    points_energy[y] / G
                points_space[y] = points_space[y] + (A - points_space[y]) / D
                points_energy[y] = points_energy[y] / H

                if (points_space[y] < B):
                    points_energy[y] = points_space[y] - B
                    points_space[y] = B

                points[y] = points[y] + points_space[y]

                if (min_x > points[y]):
                    min_x = points[y]

                self.canvas.create_line(last_x, last_y, points[y], y)
                last_x = points[y]
                last_y = y


if __name__ == "__main__":
    root = tk.Tk()
    m = Morphogenic(root)
    m.pack(fill="both", expand=True)
    m.rand()
    m.draw()
    root.mainloop()

Is tkinter just too weak for this kind of work? Should I be looking at a different 2D library?

Upvotes: 2

Views: 4949

Answers (2)

Svend Feldt
Svend Feldt

Reputation: 778

I used Tk for an application as well.

It was an application with an auto generated GUI from XML files, and TK was simply too slow.

I Switched to PYside and have been very happy about it. Its not as easy to use as Tkinter, but its much faster and has a lot of posibilities

Upvotes: 1

Bryan Oakley
Bryan Oakley

Reputation: 385980

Your code is creating over 150,000 lines. This is starting to push the performance of the canvas widget. It can pretty easily handle thousands of items, even tens of thousands of items. 150,000 items is a bit more than it was designed to handle.

Upvotes: 2

Related Questions