[PyQt] CPU spin and an error when using QQuickPaintedItem

Russell Warren russ at perspexis.com
Sat Nov 19 23:31:57 GMT 2016


I'm having a CPU-spinning problem, together with an odd QObject::killTimer
error, with a basic use case of QQuickPaintedItem.

I've reduced the example down so that the meat of it is just this:

1. Create a QGraphicsScene with some QGraphicsItems in it
2. Create a QQuickPaintedItem to render the scene to QML
3. Call QGraphicsScene.render(painter) inside the .paint of
QQuickPaintedItem

When I do this, it superficially works as I want, but I get an error to
stdout, and the CPU spins to 100%. Using strace it can be seen that the CPU
is spinning on a poll(), like seen in this capture:

https://i.snag.gy/I6QZvH.jpg

The FDs being polled are a socket and an 'anon_inode:[eventfd]', which is
(I think) the normal Qt event loop.

The error that results is this:

    $ python HeatMapProblem.py
    QObject::killTimer: Timers cannot be stopped from another thread

This timer problem is probably related, because the spinning is likely what
would happen with a zero timeout timer.

Everything *seems* like it is being done correctly from the Qt side of
things. Is there something wrong I'm doing with PyQt?

Basic code below (two files... heatmap.qml and HeatMapProblem.py).

Thanks,
Russ

#####
### heatmap.qml
#####

import QtQuick 2.0
import QtQuick.Window 2.2
import Heatmap 1.0

Window {
    visible: true
    width: 500
    height: 500
    MyHeatmap {
        anchors.fill: parent
    }
}

#####
### HeatMapProblem.py
#####
#!/usr/bin/env python
import random

from OpenGL import GL   # workaround for Nvidia issue on linux (see
http://goo.gl/pGPgVz)
import PyQt5.QtWidgets as QtWidgets
from PyQt5.QtQuick import QQuickItem, QQuickPaintedItem, QQuickView
import PyQt5.QtCore as QtCore
import PyQt5.QtGui as QtGui
import PyQt5.QtQml as QtQml

class MyPolygon(QtWidgets.QGraphicsPolygonItem):
    def __init__(self, PolyPoints, parent = None):
        super(MyPolygon, self).__init__(PolyPoints, parent)
        color = QtGui.QColor(*(random.randint(0, 128) for x in range(3)))
        self.setBrush(QtGui.QBrush(color))

class MyScene(QtWidgets.QGraphicsScene):
    def __init__(self, parent=None):
        super(MyScene, self).__init__(parent)
        blackPen = QtGui.QPen(QtCore.Qt.black, 1)
        blackPen.setCosmetic(True)

        numWide = numHigh = 3
        boxes = []
        for x in range(numWide):
            for y in range(numHigh):
                bl = (x*10,      y*10)
                tl = (x*10     , y*10 + 10)
                tr = (x*10 + 10, y*10 + 10)
                br = (x*10 + 10, y*10)
                polyDef = [bl, tl, tr, br, bl]
                poly = QtGui.QPolygonF([QtCore.QPointF(x, y) for (x, y) in
polyDef])
                item = MyPolygon(poly, parent = None)
                item.setPen(blackPen) #polygon border
                self.addItem(item)

class MyQMLScene(QQuickPaintedItem):
    def __init__(self, parent = None):
        super(MyQMLScene, self).__init__(parent)
        self._Scene = MyScene(parent = self)

    def paint(self, painter):
        self._Scene.render(painter)  # NOTE: comment this out and no
problems exist!
        pass

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    QtQml.qmlRegisterType(MyQMLScene, "Heatmap", 1, 0, "MyHeatmap")
    engine = QtQml.QQmlApplicationEngine()
    engine.load("heatmap.qml")
    sys.exit(app.exec_())
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20161119/d67d0138/attachment.html>


More information about the PyQt mailing list