Почему моя простая программа python gtk + cairo работает так медленно / заикается?

Моя программа рисует круги, перемещающиеся по окну. Я думаю, что мне не хватает базовой концепции gtk / cairo, потому что она работает слишком медленно / заикается за то, что я делаю. Есть идеи? Спасибо за любую помощь!

#!/usr/bin/python import gtk import gtk.gdk as gdk import math import random import gobject # The number of circles and the window size. num = 128 size = 512 # Initialize circle coordinates and velocities. x = [] y = [] xv = [] yv = [] for i in range(num): x.append(random.randint(0, size)) y.append(random.randint(0, size)) xv.append(random.randint(-4, 4)) yv.append(random.randint(-4, 4)) # Draw the circles and update their positions. def expose(*args): cr = darea.window.cairo_create() cr.set_line_width(4) for i in range(num): cr.set_source_rgb(1, 0, 0) cr.arc(x[i], y[i], 8, 0, 2 * math.pi) cr.stroke_preserve() cr.set_source_rgb(1, 1, 1) cr.fill() x[i] += xv[i] y[i] += yv[i] if x[i] > size or x[i] < 0: xv[i] = -xv[i] if y[i] > size or y[i] < 0: yv[i] = -yv[i] # Self-evident? def timeout(): darea.queue_draw() return True # Initialize the window. window = gtk.Window() window.resize(size, size) window.connect("destroy", gtk.main_quit) darea = gtk.DrawingArea() darea.connect("expose-event", expose) window.add(darea) window.show_all() # Self-evident? gobject.idle_add(timeout) gtk.main() 

3 Solutions collect form web for “Почему моя простая программа python gtk + cairo работает так медленно / заикается?”

Одна из проблем заключается в том, что вы снова и снова рисуете один и тот же базовый объект. Я не уверен в качестве буферизации GTK +, но также помню, что основные вызовы функций несут затраты на Python. Я добавил счетчик кадров к вашей программе, и я с вашим кодом, я получил около 30fps макс.

Есть несколько вещей, которые вы можете сделать, например, создавать более крупные пути, прежде чем на самом деле называть любой метод заполнения или инсульта (т. Е. Будут все дуги в один вызов). Другое решение, которое намного быстрее, состоит в том, чтобы скомпоновать ваш мяч в буфер вне экрана, а затем просто красить его на экране несколько раз:

 def create_basic_image(): img = cairo.ImageSurface(cairo.FORMAT_ARGB32, 24, 24) c = cairo.Context(img) c.set_line_width(4) c.arc(12, 12, 8, 0, 2 * math.pi) c.set_source_rgb(1, 0, 0) c.stroke_preserve() c.set_source_rgb(1, 1, 1) c.fill() return img def expose(sender, event, img): cr = darea.window.cairo_create() for i in range(num): cr.set_source_surface(img, x[i], y[i]) cr.paint() ... # your update code here ... darea.connect("expose-event", expose, create_basic_image()) 

Это дает около 273 кадров в секунду на моей машине. Из-за этого вам следует подумать об использовании gobject.timeout_add а не idle_add .

Я не вижу ничего принципиально неправильного в вашем коде. Чтобы сузить проблему, я попробовал другой подход, который может быть минимально быстрее, но разница почти незначительна:

 class Area(gtk.DrawingArea): def do_expose_event(self, event): cr = self.window.cairo_create() # Restrict Cairo to the exposed area; avoid extra work cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() cr.set_line_width(4) for i in range(num): cr.set_source_rgb(1, 0, 0) cr.arc(x[i], y[i], 8, 0, 2 * math.pi) cr.stroke_preserve() cr.set_source_rgb(1, 1, 1) cr.fill() x[i] += xv[i] y[i] += yv[i] if x[i] > size or x[i] < 0: xv[i] = -xv[i] if y[i] > size or y[i] < 0: yv[i] = -yv[i] self.queue_draw() gobject.type_register(Area) # Initialize the window. window = gtk.Window() window.resize(size, size) window.connect("destroy", gtk.main_quit) darea = Area() window.add(darea) window.show_all() 

Кроме того, переопределение DrawingArea.draw () с заглушкой не имеет существенного отличия.

Я бы, наверное, попробовал список рассылки в Каире или посмотрел на Clutter или pygame для рисования большого количества элементов на экране.

У меня такая же проблема в программе была написана на C #. Прежде чем покинуть событие Expose , попробуйте написать cr.dispose() .

  • ImportError: нет модуля с именем _backend_gdk
  • В GTK, как мне получить фактический размер виджета на экране?
  • pygtk как встроить внешнее приложение в мой графический интерфейс pygtk
  • Остановить графический интерфейс pygtk от блокировки во время длительного процесса
  • Создание скриншота файла gtk.Window
  • Виджет gtk TextView не обновляется во время работы
  • Пакет Python установлен глобально, но не в virtualenv (PyGTK)
  • #! / usr / bin / env python: команда не найдена и разрешение отклонено
  •  
    Interesting Posts for Van-Lav

    Ограниченная оценка наименьших квадратов в Python

    Как установить EasyGUI на Mac OS X 10.6 (Snow Leopard)?

    Как я могу использовать executeemany для вставки в MySQL списка словарей в Python

    Как проверить текстовый файл существует и не пуст в python

    Эффективный демона Python

    Как я могу использовать автоматически созданный неявный класс модели в Django в поле ForeignKey?

    Насколько эффективен / быстрый Python 'in'? (Временная сложность)

    В чем разница между родительским и ссылочным свойством в Google App Engine?

    почему некоторые выражения, которые ссылаются на “ xy“, меняют “ id (xy) “?

    Django – перенаправление на версию с www

    Выдержка из динамического ответа JSON с помощью Scrapy

    Сканирование списка

    Быстрый (векторизованный) способ найти точки в одном DF, принадлежащие прямоугольникам одинакового размера (заданные двумя точками) со второго DF

    Что такое быстрый и pythonic / чистый способ удаления отсортированного списка из другого отсортированного списка в python?

    Передача данных через классы Tkinter

    Python - лучший язык программирования в мире.