Почему является мой простой 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()
10
задан shino 31 January 2010 в 17:04
поделиться

3 ответа

Вы можете использовать либо

$(this).closest('.comment').find('form').eq(0).toggle('slow');

, либо

$(this).closest('.comment').find('form:first').toggle('slow');
-121--1327722-

Во-первых, получить некоторые дженерики там. Они находятся на Яве с 2004 года. Даже версия Java SE, которая их представила, завершила свой период окончания срока службы.

(Как точки @ finnw, я забыл о плохом старом Java ME. Если вам придется использовать Java ME, то вам придется отказаться от дженериков и кастинга (но не instanceof часто) до тех пор, пока он (включая развернутые устройства) не превратится в 2004.)

Использование instanceof и casting указывает на плохой дизайн. Вероятно, было бы лучше поместить в список объект с интерфейсом, который клиентский код может использовать без тестов, и реализации, которые сопоставляются с различным поведением для каждой «реальной» цели списка. "Каждая проблема в информатике может быть решена добавлением другого уровня косвенности" [... " за исключением слишком большого количества уровней косвенности. "]

-121--3250456-

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

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

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 _ добавления , а не idle _ добавления .

11
ответ дан 3 December 2019 в 23:50
поделиться

Вместе с javascripts для отслеживания событий GUI и создания сценариев новых элементов HTML 5, вы получаете много того, что предлагает Flash.

HTML- 5 содержит ряд новых элементов. Один из них называется Холст. С его помощью вы можете нарисовать все, что хотите, на экране, в пределах его границ. Вы используете javascript, чтобы нарисовать на нем, и вы можете поймать любые mouseclicks и тому подобное с javascript тоже. Если вы используете инструменты графического интерфейса на рабочем столе, такие как Tk, GTK, вы можете сравнить эти новые элементы с некоторыми виджетами этих инструментов графического интерфейса.

Посмотрите на jit , чтобы увидеть пример графиков в HTML 5

-121--1836520-

Невозможно хранить методы в массивах Java, поскольку методы не являются первоклассными объектами Java. Это причина, почему некоторые люди предпочитают использовать другие языки, такие как Python, Scheme и т.д.

Рабочая группа состоит в том, чтобы создать интерфейс, который содержит один метод, а затем создать четыре класса, реализующих этот интерфейс - MireRight, MireLeft и т.д. классы. Затем можно сохранить экземпляры этих классов в массиве и вызвать их все те же пути.

-121--3235623-

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

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, чтобы нарисовать большое количество пунктов на экране.

2
ответ дан 3 December 2019 в 23:50
поделиться

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

0
ответ дан 3 December 2019 в 23:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: