如何快速绘制10000多个二维图形对象?

2024-04-20 04:31:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要在一个小部件上绘制成千上万个,将来可能会有几十万个简单的二维对象(圆、矩形、一些填充、标记…)。在

在同一个程序中,我需要GUI小部件(按钮、文本输入、复选框)。在

<>我用C++和Python尝试了GTK、QT和SDL。第一个结果是可以预料到的:C++和Python显示相同的性能,因为它们在后端调用相同的C或C++例程。在

第二个结果是,没有一个图书馆有很大的不同。在数量上:22500个矩形(150*150)需要大约一秒钟的时间来更新。由于(a)新数据(即更多矩形)和(b)用户交互,即缩放、平移等,会有持续的升级,第二种方法是long!在

什么是更快的方法。小例子非常感谢。Python和C++是很好的。其他库应该在Linux上易于访问和安装。在

也许我只是做错了。在

另外,我不发布我的测试代码,因为我不想有偏见的答案。我不想我的代码被更正,我想用最快的方法来做。。。在

编辑:

好的,我将添加我的gtk测试:

#!/bin/env python2

import gtk
import gobject
import gtk.gdk

class GraphWidget(gtk.DrawingArea):
    __gsignals__ = {
        'expose-event': 'override',
        'clicked' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gtk.gdk.Event))
        }

    def __init__(self,window):
        gtk.DrawingArea.__init__(self)
        #self.win = window
        self.zoom_ratio = 1.0
        self.dx = 40
        self.dy = 40

    def do_expose_event(self, event):
        cr = self.window.cairo_create()
        cr.set_source_rgba(1.0, 0.9, 0.8, 1.0)
        cr.paint()

        cr.translate(self.dx, self.dy)
        cr.scale(self.zoom_ratio,self.zoom_ratio)

        self.draw(cr)

    def draw(self, cr):
        n = 150
        cr.set_source_rgba(0.,1.,1.,1.0)
        for i in range(n):
            for j in range(n):
                cr.arc(i*30, j*30, 10, 0, 6.2832)

                cr.close_path()
                cr.fill()

        cr.set_source_rgba(0.,0.,1.,1.0)
        for i in range(n):
            for j in range(n):
                cr.arc(i*30, j*30, 10, 0, 6.2832)
                cr.move_to(i*30-10, j*30)
                cr.show_text("hu")
                cr.stroke()

    def on_zoom(self, zoom_factor):
        self.zoom_ratio *= zoom_factor
        self.queue_draw()

    def on_translate(self,dx,dy):
        self.dx += dx
        self.dy += dy
        self.queue_draw()

class TestWindow(gtk.Window):
    def __init__(self):
        gtk.Window.__init__(self)

        self.widget = GraphWidget(self)

        self.add(self.widget)

        self.show_all()

        # connect key press events

        self.connect('key-press-event', self.on_key_press_event)
        self.connect('destroy', gtk.main_quit)

        self.widget.queue_draw()

    def on_key_press_event(self, widget, event):

        if event.keyval == gtk.keysyms.space and not (event.state & gtk.gdk.CONTROL_MASK):
            self.on_run(widget)
            return True
        elif event.keyval == gtk.keysyms.r:
            self.on_refresh(widget)
            return True
        elif event.keyval == gtk.keysyms.Left:
            self.widget.on_translate(-100, 0)
        elif event.keyval == gtk.keysyms.Right:
            self.widget.on_translate(100, 0)
        elif event.keyval == gtk.keysyms.Up:
            self.widget.on_translate(0, -100)
        elif event.keyval == gtk.keysyms.Down:
            self.widget.on_translate(0, 100)
        elif event.keyval == gtk.keysyms.Page_Down:
            self.widget.on_zoom(0.7)
        elif event.keyval == gtk.keysyms.Page_Up:
            self.widget.on_zoom(1.3)

if __name__ == '__main__':
    win = TestWindow()
    gtk.main()

SDL实验:

^{pr2}$

Qt测试是我同事做的,所以我现在没有代码。。。在


Tags: selfeventgtkondefwidgettranslatecr
1条回答
网友
1楼 · 发布于 2024-04-20 04:31:45

看起来你正在绘制每个对象,不管它是否在可视区域。你有没有考虑过存储一个每个对象的位置数组,然后在绘制之前测试每个对象是否在屏幕的可视区域中?在

我做了一个快速而肮脏的测试来尝试它(代码可以更干净,我确信),而且只绘制可见的内容会更具响应性:

首先,我创建了一些变量来确定可见边界(每次移动和缩放、窗口大小调整等发生时,都会更新边界):

boundX = [-60, 160]
boundY = [-60, 160]

在draw事件中,我在绘制之前检查位置是否在边界内。我还合并了你的循环以提高效率,你可以在同一个迭代中绘制和添加文本。即使用n = 50000来测试它,也比以前更能反应。在

^{pr2}$

在keypress事件中,只需根据小部件的翻译量来增加和减少边界:

def on_key_press_event(self, widget, event):

    if event.keyval == gtk.keysyms.space and not (event.state & gtk.gdk.CONTROL_MASK):
        self.on_run(widget)
        return True
    elif event.keyval == gtk.keysyms.r:
        self.on_refresh(widget)
        return True
    elif event.keyval == gtk.keysyms.Left:
        boundX[0] += 100
        boundX[1] += 100
        self.widget.on_translate(-100, 0)
    elif event.keyval == gtk.keysyms.Right:
        boundX[0] -= 100
        boundX[1] -= 100
        self.widget.on_translate(100, 0)
    elif event.keyval == gtk.keysyms.Up:
        boundY[0] += 100
        boundY[1] += 100
        self.widget.on_translate(0, -100)
    elif event.keyval == gtk.keysyms.Down:
        boundY[0] -= 100
        boundY[1] -= 100
        self.widget.on_translate(0, 100)
    elif event.keyval == gtk.keysyms.Page_Down:
        self.widget.on_zoom(0.7)
    elif event.keyval == gtk.keysyms.Page_Up:
        self.widget.on_zoom(1.3)

相关问题 更多 >