Я создал простое приложение для отображения диаграммы рассеяния данных с помощью виджета Tkinter Canvas (см. простой пример ниже). После построения 10 000 точек данных приложение становится очень медленным, в чем можно убедиться, попробовав изменить размер окна.
Я понимаю, что каждый элемент, добавленный в Canvas, является объектом, поэтому в какой-то момент могут возникнуть некоторые проблемы с производительностью, однако я ожидал, что этот уровень будет намного выше, чем 10 000 простых овальных объектов. Кроме того, я мог бы принять некоторые задержки при рисовании точек или взаимодействии с ними, но после того, как они нарисованы, почему простое изменение размера окна может быть таким медленным?
После прочтения о проблемах производительности effbot с виджетом Canvas кажется, что во время работы могут возникать ненужные непрерывные незанятые задачи. изменение размера, которое необходимо игнорировать:
Виджет Canvas реализует простую модель отображения повреждений/восстановления. Изменения на холсте и внешние события, такие как Expose, рассматриваются как «повреждение» экрана. Виджет поддерживает грязный прямоугольник, чтобы отслеживать поврежденную область.
Когда приходит первое событие повреждения, холст регистрирует бездействующую задачу (используя after_idle), которая используется для «восстановления» холста, когда программа возвращается к основному циклу Tkinter. Вы можете принудительно выполнить обновления, вызвав метод update_idletasks.
Итак, вопрос в том, есть ли способ использовать update_idletasks
, чтобы сделать приложение более отзывчивым после того, как данные были нанесены на график? Если да, то как?
Ниже приведен простейший рабочий пример. Попробуйте изменить размер окна после его загрузки, чтобы увидеть, насколько медленным становится приложение.
Обновлять
Первоначально я наблюдал эту проблему в Mac OS X (Mavericks), где я получаю значительный всплеск загрузки ЦП при простом изменении размера окна. Под влиянием комментариев Рамчандры я проверил это в 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