Ubuntourist Ubuntourist - 9 days ago 5
Python Question

I don't understand why I'm getting QPainter::begin: Widget painting can only begin as a result of a paintEvent

I've been looking at other StackOverflow questions regarding this error (and elsewhere on the web) but I don't understanding how the answers relate to my code. So, I'm hoping for either a fixed example that makes sense to me, or a better explanation of how and when events occur.

The code below was intended to figure out the dimensions of the screen it's running on, resize to that and draw a circle in the center that occupies most of the available screen real estate. It tried to do a lot more, but I've stripped it down -- enough, I hope. Now it just tries to draw a circle.

#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import sys

from PySide.QtCore import *
from PySide.QtGui import *


class Viewport(QGraphicsView):

def __init__(self, parent=None):
super(Viewport, self).__init__(parent)

self.scene = QGraphicsScene(self)
self.setScene(self.scene)

def paintEvent(self, event):
super(Viewport, self).paintEvent(event)

qp = QPainter()
qp.begin(self)
square = QRect(10, 10, 30, 30)
qp.drawEllipse(square)
qp.end()


class UI(QDialog):

def __init__(self, parent=None):
super(UI, self).__init__(parent)

self.view = Viewport(self)
gridLayout = QGridLayout()
gridLayout.addWidget(self.view, 0, 0, 1, 1)
self.setLayout(gridLayout)

def resizeEvent(self, event):
super(UI, self).resizeEvent(event)
self.view.setFrameShape(QFrame.NoFrame)
self.view.setSceneRect(0, 0, 400, 400)
self.view.setFixedSize(400, 400)


app = QApplication(sys.argv)

ui = UI()
ui.show()

sys.exit(app.exec_())


The above was stripped out of broken code that had a moving SVG item and the circle originally had a gradient fill. The SVG item was displaying and moving okay but the circle never showed up.

The gradient-filled circle worked fine in another program when it was in a drawn by a paintEvent for a QGroupBox, but I cannot grok how QGraphicsScene and QGraphicsView work.

UPDATED

The error message, exactly as I see it (sadly w/o line numbers):

$ ./StackOverflow.py
QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::end: Painter not active, aborted

Answer

You need to paint on the viewport():

    def paintEvent(self, event):
        super(Viewport, self).paintEvent(event)

        qp = QPainter()
        qp.begin(self.viewport())

        square = QRect(10, 10, 30, 30)
        qp.drawEllipse(square)
        qp.end()