Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QGraphicsView - Smooth Rescaling quality (PyQt5)



  • I am trying to create a "clone" of Gwenview with some extra (very) specific features. One of the key features is the ability to display multiple media (images, gifs, videos and audio) in a grid.

    I had a first implementation using QLabel to display Pixmap and it was working perfectly. I decided to try QGraphicsView for the ability to display videos as well but the quality of the images is often atrocious:

    alt text

    I can try to provide the relevant part of the code (I am, however, using PyQt5 bindings and no C++) because the full code is quite a mess at the moment:

    Left - QGraphicsView Implementation:

    class clsMediaView(QtWidgets.QGraphicsView):
      # ----------------------------------------------------------------------------
      def __init__(self, filePath):
        self.scene = QtWidgets.QGraphicsScene()
        super().__init__(self.scene)
        self.filePath = filePath
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
        self.setAlignment(QtCore.Qt.AlignCenter)
        self.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.SmoothPixmapTransform)
    
        self.media = QtGui.QPixmap(self.filePath)
        self.item = QtWidgets.QGraphicsPixmapItem(self.media)
        self.scene.addItem(self.item)
        self.fitInView(self.item, QtCore.Qt.KeepAspectRatio)
    
      # ----------------------------------------------------------------------------
      def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
        super().resizeEvent(a0)
        self.fitInView(self.item, QtCore.Qt.KeepAspectRatio | QtCore.Qt.SmoothTransformation)
    

    Right - QLabel Implementation:

    class clsMediaView(QtWidgets.QLabel):
      # ----------------------------------------------------------------------------
      def __init__(self, filePath):
        super().__init__()
        self.filePath = filePath
        self.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
        self.setAlignment(QtCore.Qt.AlignCenter)
        self.media = QtGui.QPixmap(self.filePath)
        self.setPixmap(self.media)
        
      # ----------------------------------------------------------------------------  
      def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
        super().resizeEvent(a0)
        self.setPixmap(self.media.scaled(self.size(), QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation))
    

    Am I doing something obviously wrong? Thanks in advance?


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Looks like you are missing a call to QGraphicsPixmapItem::setTransformationMode.



  • erm... bump?


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Looks like you are missing a call to QGraphicsPixmapItem::setTransformationMode.



  • @SGaist Indeed, thanks!



  • Actually, let me reiterate - it does NOT solve the problem, though it does look better.
    Antialiasing is still missing.

    And apparently, after some googling, the setRenderHints are ignored by the painter device for some reason. Several people suggest another workaround:

      # ----------------------------------------------------------------
      def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
        super().resizeEvent(a0)
        self.item.setPixmap(self.media.scaled(self.size(), QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation))
    

    In this case, fitInView/setRenderHints/setTransformationMode and so on are not even needed. This solution, however, completely ruins the alignment. Resizing the window causes the item to lose the center-alignment.

    I'm sorry, but isn't this a bug?


  • Lifetime Qt Champion

    Do you have the links to these renderHints comment ?

    Which resizeEvent is that ?



  • @SGaist said in QGraphicsView - Smooth Rescaling quality (PyQt5):

    Do you have the links to these renderHints comment ?

    See the comment of user136036, for instance:
    https://stackoverflow.com/questions/17734290/antialiasing-not-working-in-qgraphicsview

    Which resizeEvent is that ?

    This is the resizeEvent of clsMediaView (extending QGraphicsView).


  • Lifetime Qt Champion

    Is it me or did you drop the fitInView from your code ?



  • You don't need "fitInView" if you're resizing the Pixmap yourself, and you need to resize the Pixmap yourself because QGraphicsView is unable to support antialiasing. I would argue that that should be the default behaviour, but I have given up the whole QGraphicsView thing altogether.


Log in to reply