2016-07-11 12 views
2

Ich mache eine GUI in Python mit Tkinter und hatte einige Leistungsprobleme beim Packen viele Widgets auf dem Bildschirm, zum Beispiel ein 50x50 Raster von Schaltflächen packt dauert ein paar Sekunden.Tkinter Leistung beim Packen viele Widgets

Es scheint der Prozess der Zeichnung (oder Anordnung?) Der Widgets auf dem Bildschirm, die die Zeit nimmt. Ich habe versucht, sowohl den Raster- als auch den Platzgeometrie-Manager zu verwenden.

Ich frage mich, ob Multiprocessing dies beschleunigen könnte? Ich würde gerne andere Vorschläge für eine Art und Weise begrüßen, in der dies erheblich beschleunigt werden könnte.

import Tkinter as tk 

root = tk.Tk() 
frame = tk.Frame(root) 
for i in range(50): 
    for j in range(50): 
     widget = tk.Frame(frame, bd=2, relief='raised', height=10, width=10) 
     widget.grid(row=i, column=j) # using place is barely quicker 
tk.Button(root, text='pack', command=frame.pack).pack() 
root.mainloop() 
+0

Tkinter nicht threadsicher ist, so wird Multiprozessing an Sicherheit grenzender Wahrscheinlichkeit nicht helfen, ich persönlich fand, dass in einigen Fällen, dass Sie die Widgets auf einer Leinwand platzieren [ 'canvas.create_window'] (http: //infohost.nmt. edu/tcc/help/pubs/tkinter/web/create_window.html) war schneller neu zu zeichnen, aber schwieriger zu resize/manipulieren. –

+0

@ TadhgMcDonald-Jensen Ich habe es gerade mit dem obigen Beispiel versucht und der Unterschied ist minimal, wenn überhaupt. – Siwel

+1

Ich meine ... Sie instanziieren 2500 Objekte, die alle instanziierte, einzigartige Schlüssel generieren, in den Tcl-Interpreter übertragen und dort instanziiert, vorwärts und rückwärts gebunden und dann arrangiert werden müssen. Soweit GUIs gehen, ist 2500 Objekte in der Regel ein wenig viel durch einen Wrapper von einer interpretierten Sprache zur anderen zu gehen. Was ist dein Ziel? Wenn du nur ein gitterähnliches Konstrukt haben willst, verwende keine 2500 Frames, benutze eine Leinwand und zeichne einige Quadrate (weniger/einfachere Objekte) – Delioth

Antwort

0

Wie in den Kommentaren vorgeschlagen, hat die beste Lösung, die eine Leinwand zu verwenden, am Ende wurde und auf sie zu ziehen, anstatt so viele Widgets zu packen, die absoluten Einschränkungen auf seiner Geschwindigkeit zu haben scheint.

Ich habe die integrierten Schaltflächen verwendet, indem ich effektiv einen Screenshot gemacht habe, um Bilder der nicht geklickten und geklickten Zustände zu erstellen. Angenommen, die Bilddateien werden als im_up.png und im_down.png gespeichert, dann veranschaulicht der folgende Code die Canvas-Lösung.

import Tkinter as tk 
# Uses Python Imaging Library. 
from PIL import Image as ImagePIL, ImageTk 

root = tk.Tk() 
canvas = tk.Canvas(root, height=500, width=500, highlightthickness=0) 
canvas.pack() 
images = dict() 
for name in ['up', 'down']: 
    im = ImagePIL.open('im_{}.png'.format(name)) 
    # Resize the image to 10 pixels square. 
    im = im.resize((10, 10), ImagePIL.ANTIALIAS) 
    images[name] = ImageTk.PhotoImage(im, name=name) 
def set_cell_image(coord, image): 
    # Get position of centre of cell. 
    x, y = ((p + 0.5) * 10 for p in coord) 
    canvas.create_image(x, y, image=image) 
for i in range(50): 
    for j in range(50): 
     set_cell_image((i, j), images['up']) 
def click(event): 
    coord = tuple(getattr(event, p)/10 for p in ['x', 'y']) 
    set_cell_image(coord, images['down']) 
canvas.bind('<Button-1>', click) 
root.mainloop() 
Verwandte Themen