Improving performance of animated shape drawing using Python Qt5 QPainter

huangapple go评论58阅读模式
英文:

Improving performance of animated shape drawing using Python Qt5 QPainter

问题

在我的Qt5应用程序中,我需要在小部件上绘制多个自定义动画形状(多边形、图标等)。目前,这导致每个绘制周期都要实例化大量的QPoint,因为我需要在每个时间帧中更新每个QPolygon中的每个点。我想知道是否有一种更少丑陋、性能更好/更直接的方法来做到这一点。我已经将所有的点都存储在单个内存块中。对我来说,将其拆分为单个QPoint对象是没有意义的。

我的伪代码实现目前如下:

  1. 计算所有点并将其存储为numpy数组中的行
  2. 在循环中,逐个将所有点从numpy数组复制到QPoint实例中
  3. 将所有QPoints传递给QPolygon
  4. 使用QPainter绘制多边形

在PyQt5中是否有更好的方法/实现可能?

我想要的是消除这些丑陋的步骤2和3:

  1. 计算所有点(大量代数运算,因此在numpy中完成)
  2. 将numpy数组的内存块传递给QPolygon,并定义它应该如何解释
  3. 绘制多边形
英文:

In my Qt5 application I need to draw several animated custom shapes on a widget (several polygons, icons, etc). Currently this results in lots of QPoints being instantiated every paint cycle, since i need to update every point of every QPolygon in every time frame. I'm wondering whether there is a less ugly and more performant/direct way to do this. I already have all my points given in a single memory block. To me it makes no sense in splitting it up and into single QPoint objects.

My pseudo implementation currently looks like this:

  1. Compute all points and store as rows in numpy array
  2. In a loop, copy all points from numpy array to QPoint instances one by one
  3. Pass all QPoints to QPolygon
  4. Draw polygon using QPainter

Is there any better approach/implementation possible in PyQt5?

What i'd like to have is those ugly steps 2 and 3 eliminated:

  1. Compute all points (lots of algebra, hence this is done in numpy)
  2. Pass memory block of numpy array to QPolygon and define how it has to be interpreted
  3. Draw polygon

答案1

得分: 0

我找到了一个相对简单的解决方案,可以消除逐个复制所有点的循环。诀窍是预先分配QPolygon,获取其sip.voidptr并将其解释为NumPy数组。以下是一个示例:

poly = QPolygonF([QPointF(10, 10)] * 3)
src = np.array([1, 2, 3, 4, 5, 6])

ptr = poly.data()
ptr.setsize(8 * poly.size() * 2)

dest = np.frombuffer(ptr)
dest[:] = src

不幸的是,我必须手动设置ptr的大小,但至少我可以使用这种方法将计算结果直接写入多边形的内存中(有人知道如何获取由QPolygon引用的数据的字节大小吗?)。

这是我找到sip.voidptr所需提示的帖子

英文:

I found a somewhat simple solution which eliminates the loop to copy all the points one by one. The trick is to pre-allocate the QPolygon, get its sip.voidptr and interpret it as numpy array. Here's an example:

poly = QPolygonF([QPointF(10, 10)] * 3)
src = np.array([1, 2, 3, 4, 5, 6])

ptr = poly.data()
ptr.setsize(8 * poly.size() * 2)

dest = np.frombuffer(ptr)
dest[:] = src

Unfortunately, I have to set the size of ptr manually, but at least I can use this approach to write the computation results directly into the polygons memory (does anyone know how to get the byte size of the data referenced by QPolygon?).

Here's the post where I found the necessary hint with the sip.voidptr

huangapple
  • 本文由 发表于 2023年5月10日 15:34:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76215961.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定