Създадох просто приложение за показване на диаграма на разсейване на данни, използвайки изпълнимия модул Canvas на Tkinter (вижте простия пример по-долу). След начертаване на 10 000 точки от данни, приложението става много бавно, което може да се види, като се опитате да промените размера на прозореца.
Осъзнавам, че всеки елемент, добавен към Canvas, е обект, така че в даден момент може да има проблеми с производителността, но очаквах това ниво да бъде много по-високо от 10 000 прости овални обекта. Освен това, бих могъл да приема някои закъснения при изчертаване на точките или взаимодействие с тях, но след като те са начертани, защо просто преоразмеряването на прозореца ще бъде толкова бавно?
След като прочетох проблеми с производителността на effbot с приспособлението Canvas, изглежда, че може да има някои ненужни непрекъснати неактивни задачи по време преоразмеряване, което трябва да се игнорира:
Уиджетът Canvas реализира директен модел на показване на повреди/поправки. Промените в платното и външни събития като Expose се третират като „повреди“ на екрана. Джаджата поддържа мръсен правоъгълник, за да следи повредената зона.
Когато пристигне първото събитие за повреда, платното регистрира неактивна задача (използвайки after_idle), която се използва за „поправяне“ на платното, когато програмата се върне към основния цикъл на Tkinter. Можете да принудите актуализациите, като извикате метода update_idletasks.
И така, въпросът е дали има някакъв начин да се използва update_idletasks
, за да се направи приложението по-отзивчиво, след като данните са начертани? Ако е така, как?
По-долу е най-простият работещ пример. Опитайте да преоразмерите прозореца, след като се зареди, за да видите колко бавно става приложението.
Актуализация
Първоначално наблюдавах този проблем в Mac OS X (Mavericks), където получавам значителен скок в използването на процесора, когато просто преоразмерявам прозореца. Подтикнат от коментарите на Ramchandra, тествах това в Ubuntu и това не изглежда да се случва. Може би това е проблем с Mac Python/Tk? Няма да е първият, на когото се натъквам, вижте другия ми въпрос:
PNG дисплей в PIL е повреден на OS X Mavericks?
Може ли някой да опита и в Windows (нямам достъп до кутия с Windows)?
Може да опитам да стартирам на Mac със собствената си компилирана версия на Python и да видя дали проблемът продължава.
Минимален работен пример:
import Tkinter
import random
LABEL_FONT = ('Arial', 16)
class Application(Tkinter.Frame):
def __init__(self, master, width, height):
Tkinter.Frame.__init__(self, master)
self.master.minsize(width=width, height=height)
self.master.config()
self.pack(
anchor=Tkinter.NW,
fill=Tkinter.NONE,
expand=Tkinter.FALSE
)
self.main_frame = Tkinter.Frame(self.master)
self.main_frame.pack(
anchor=Tkinter.NW,
fill=Tkinter.NONE,
expand=Tkinter.FALSE
)
self.plot = Tkinter.Canvas(
self.main_frame,
relief=Tkinter.RAISED,
width=512,
height=512,
borderwidth=1
)
self.plot.pack(
anchor=Tkinter.NW,
fill=Tkinter.NONE,
expand=Tkinter.FALSE
)
self.radius = 2
self._draw_plot()
def _draw_plot(self):
# Axes lines
self.plot.create_line(75, 425, 425, 425, width=2)
self.plot.create_line(75, 425, 75, 75, width=2)
# Axes labels
for i in range(11):
x = 75 + i*35
y = x
self.plot.create_line(x, 425, x, 430, width=2)
self.plot.create_line(75, y, 70, y, width=2)
self.plot.create_text(
x, 430,
text='{}'.format((10*i)),
anchor=Tkinter.N,
font=LABEL_FONT
)
self.plot.create_text(
65, y,
text='{}'.format((10*(10-i))),
anchor=Tkinter.E,
font=LABEL_FONT
)
# Plot lots of points
for i in range(0, 10000):
x = round(random.random()*100.0, 1)
y = round(random.random()*100.0, 1)
# use floats to prevent flooring
px = 75 + (x * (350.0/100.0))
py = 425 - (y * (350.0/100.0))
self.plot.create_oval(
px - self.radius,
py - self.radius,
px + self.radius,
py + self.radius,
width=1,
outline='DarkSlateBlue',
fill='SteelBlue'
)
root = Tkinter.Tk()
root.title('Simple Plot')
w = 512 + 12
h = 512 + 12
app = Application(root, width=w, height=h)
app.mainloop()
update_idletasks()
може да помогне само по време на първоначалното чертане и не засяга по-късното преначертаване на платното. Това е на Win Vista, Python 2.7.2, Tk 8.5. - person Todd   schedule 14.11.2013