[PyQt] Object-based paint/update in Qt/PyQt4

Zsolt Ero zsolt.ero at gmail.com
Tue Oct 23 13:49:37 BST 2012


I'd like to tag items by drawing polygons over an image in Python using
PyQt4. I was able to implement the image viewer with QGraphicsScene but I
don't understand the concept behind painting/updating objects.

What I'd like to do is a Polygon class, what supports adding and editing.
What confuses me is theQGraphicsScene.addItem and the different paint or
update methods. What I'd like to implement is to

   1. draw a polygon as lines while not complete
   2. draw it as a filled polygon once complete

The algorithm part is OK, what I don't understand is that how do I
implement the paint or update functions.

*Here is my confusion*

*In the original example file*: graphicsview/collidingmice there is a
special function def paint(self, painter, option, widget): what does the
painting. There is no function calling the paint function, thus I'd think
it's a special name called by QGraphicsView, but I don't understand what is
a painter and what should a paint function implement.

*On the other hand in numerous online tutorials* I find def
paintEvent(self, event): functions, what seems to follow a totally
different concept compared to the graphicsview / paint.

Maybe to explain it better: for me *the way OpenGL does the scene-update is
clear*, where you always clean everything and re-draw elements one by one.
There you just take care of what items do you want to draw and draw the
appropriate ones. There is no update method, because you are drawing always
the most up-to-date state. This Qt GUI way is new to me. *Can you tell me
what happens with an item after I've added it to the scene*? How do I *edit
something* what has been added to the scene, *where is the always updating
'loop'*?

Here is my source in the smallest possible form, it creates the first
polygon and starts printing it's points. I've arrived so far that the paint
method is called once (why only once?) and there is this
errorNotImplementedError:
QGraphicsItem.boundingRect() is abstract and must be overridden. (just copy
any jpg file as big.jpg)

Thanks, Zsolt

from __future__ import division

import sys
from PyQt4 import QtCore, QtGui

class Polygon( QtGui.QGraphicsItem ):

    def __init__(self):

        super(Polygon, self).__init__()

        self.points = []

        self.closed = False

    def addpoint( self, point ):

        self.points.append( point )

        print self.points

    def paint(self, painter, option, widget):

        print "paint"


class MainWidget(QtGui.QWidget):

    poly_drawing = False

    def __init__(self):

        super(MainWidget, self).__init__()

        self.initUI()

    def initUI(self):

        self.scene = QtGui.QGraphicsScene()

        self.img = QtGui.QPixmap( 'big.jpg' )

            self.view = QtGui.QGraphicsView( self.scene )

        self.view.setRenderHint(QtGui.QPainter.Antialiasing)

        self.view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)

            self.view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)

        self.pixmap_item = QtGui.QGraphicsPixmapItem( self.img, None,
self.scene)

            self.pixmap_item.mousePressEvent = self.pixelSelect

            self.mypoly = Polygon()

                layout = QtGui.QVBoxLayout()

            layout.addWidget( self.view )

            self.setLayout( layout )

        self.resize( 900, 600 )

        self.show()

    def resizeEvent(self, event):

        w_scale = ( self.view.width() )  / self.img.width()

        h_scale = ( self.view.height() ) / self.img.height()

        self.scale = min( w_scale, h_scale)

        self.view.resetMatrix()

        self.view.scale( self.scale, self.scale )

    def pixelSelect(self, event):

        if not self.poly_drawing:

            self.poly_drawing = True

            self.mypoly = Polygon()

            self.scene.addItem( self.mypoly )

        point = event.pos()

        self.mypoly.addpoint( point )


def main():

    app = QtGui.QApplication(sys.argv)

    ex = MainWidget()

    sys.exit(app.exec_())


if __name__ == '__main__':

    main()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20121023/fa328c3f/attachment-0001.html>


More information about the PyQt mailing list