1

I am working with PyQt5 (Version 5.15.7) in PyCharm Community on Windows 11.

I have subclassed the QGraphicsScene and added some attribute and methods I need. I add some QGraphicsItems and QGraphicsItemGroups on the scene and display it in a QMainWindow using a QGraphicsView. Now I want to store the content of the whole scene as simple PNG with transparency. I added self.setBackgroundBrush(Qt.transparent) to my QGraphicsScene subclass.

I use now the following Code to render from my QGraphicsScene into a QImage and then I store the QImage:


# Get region of scene to capture from somewhere.
areaF = self.my_scene.sceneRect()  # Return type: QRectF

# Create a QImage to render to and fix up a QPainter for it.
image = QImage( areaF.toRect().size(), Image.Format_ARGB32_Premultiplied ) 

painter = QPainter( image )

# Render the region of interest to the QImage.
painter.begin( image)
self.my_scene.render( painter,
                      QRectF( image.rect() ),  # target
                      areaF )  # source
painter.end()

# Save the image to a file.
image.save( filename[ 0 ] )

I found the code above as question here on stackoverflow and adapted it respecting to the comments. Everything is fine, BUT the PNG contains very often artifacts like this: (Enlarged screenshots from MSPaint):

This is the original picture taken as screenshot from my app

The PNG should look like the last screenshot...without these strange points and lines... The artifacts are sometimes really hard, sometimes they don't appear... Does anybody have an idea why these artifacts appear and how I could evade them?

  • `painter.setRenderHint(painter.Antialiasing)` (which is what you most probably did on the view). You also don't need to call `begin()`, since you've already created the painter with the image as argument (which automatically initializes it). Also, unless you explicitly set a custom background, there's no need for `setBackgroundBrush()`, but you **must** initialize it using `image.fill(Qt.transparent)` (see the warning in the [documentation](https://doc.qt.io/qt-5/qimage.html#QImage-2)). – musicamante Aug 23 '22 at 16:15
  • By the way, avoid adding spaces near parentheses (after opening and before closing), as it makes them a bit confusing. – musicamante Aug 23 '22 at 16:21
  • @musicamente: Sei mitico! Mille Grazie, ora funziona perfettamente :-) Per le parentesi: Per me é viceversa...se ho 10 parentesi, queste spazie mi aiutano tanto. Cambio il code con la tu risposta. Mille Grazie! – Bartek Kahl Aug 23 '22 at 16:41
  • Glad to be of help, but please keep comments in English. About the parentheses, you can obviously write *your* code as you wish, but this is a *public* space, and we should try to follow *common conventions* (see the official [Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/)); note that python (but not only) style conventions also consider nested parentheses, and the *suggested* practice is to use multiple lines with increasing indentation levels for each group of brackets, which is much better than using spaces inside parentheses. (Btw, it's "musicamAnte" :-P) – musicamante Aug 23 '22 at 22:33
  • :-) Sorry, and I will keep the parentheses as written in the Stye Guide. Will change my PyCharm-Settings for this, again. Currentyl I have set up my computer by new, because I messed up a little with venv's and so I lost control which Project/venv has which packages installed. Now I am sorting it out from scratch. Reason is I want to deploy my PyQt5-Stuff crossplattform...If you know any good tutorials...drop me a private message. Here are already enough comments. (MUSICamante ist recognized...thought it's literally translated musically, but it's musicLoving ;-) I guess...Grazie again :-) – Bartek Kahl Aug 24 '22 at 19:05

1 Answers1

1

I changed the Code according to the musicamente's comments, and it works without artifacts :-)

Here the Code with the changes applied (the method is now part of my subclassed QGraphicsScene):

    def scene_to_image( self ):
        # Get region of scene to capture from somewhere.
        areaF = self.sceneRect()  # Return type: QRectF
        # Create a QImage to render to and fix up a QPainter for it.
        image = QImage(areaF.toRect().size(),
                       QImage.Format_ARGB32_Premultiplied
                       )  
        # MUSICAmAnte :-)
        image.fill(Qt.transparent)

        painter = QPainter(image)

        # MUSICAmAnte :-)
        painter.setRenderHint(painter.Antialiasing)

        # Render the region of interest to the QImage.
        self.render(painter, 
                    QRectF(image.rect()),  # target
                    areaF                  # source
                    )
        painter.end()
        return image