繁体   English   中英

为什么我的简单python gtk + cairo程序运行如此缓慢/断断续续?

[英]Why is my simple python gtk+cairo program running so slowly/stutteringly?

我的程序绘制了在窗口上移动的圆圈。 我想我必须缺少一些基本的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()

其中一个问题是您一次又一次地绘制相同的基本对象。 我不确定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 fps。 因此,您应该考虑使用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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM