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

Pixelator example for PySide2



  • I'm trying to recreate the Pixelator example for PySide2
    https://doc.qt.io/qtforpython/overviews/qtwidgets-itemviews-pixelator-example.html#pixelator-example

    Unfortunately something is broken and I'm not getting errors nor and pixel painted. If some one can take a look at the code below and help out that would be very much appreciated.
    Thanks

    
    from PySide2 import QtGui, QtCore, QtWidgets
    
    
    class ImageModel(QtCore.QAbstractTableModel):
        def __init__(self, parent=None):
            super(ImageModel, self).__init__(parent)
            self.model_image = QtGui.QImage('art_image.jpeg') # you will have to replace this
    
        def rowCount(self, *args, **kwargs):
            return self.model_image.height()
    
        def columnCount(self, *args, **kwargs):
            return self.model_image.width()
    
        def data(self, index, role):
            if not index.isValid() or role != QtCore.Qt.DisplayRole:
                return None
            return QtGui.qGray(self.model_image.pixel(index.column(), index.row()))
    
        def headerData(self, section, orientation, role):
            if role == QtCore.Qt.SizeHintRole:
                return QtCore.QSize(1,1)
    
    
    
    class PixelDelegate(QtWidgets.QAbstractItemDelegate):
        def __init__(self, parent=None):
            super(PixelDelegate, self).__init__(parent)
            self.pixel_size = 12
    
        def paint(self, painter, option, index):
            #if option.state and QtWidgets.QStyle.State_Selected:
             #   painter.fillRect(option.rect, option.palette.highlight())
    
            size = min(option.rect.width(), option.rect.height())
            brightness = int(index.model().data(index, QtCore.Qt.DisplayRole))
            radius = (size/2.0) - (brightness/255.0 * size/2.0)
            if radius == 0.0:
                return
    
            painter.save()
            painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
            painter.setPen(QtCore.Qt.NoPen)
    
            #if option.state and QtWidgets.QStyle.State_Selected:
              #  painter.setBrush(option.palette.highlightedText())
         
            painter.setBrush(QtGui.QBrush(QtCore.Qt.black))
            painter.drawEllipse(QtCore.QRectF(option.rect.x() + option.rect.width() / 2 - radius,
                                           option.rect.y() + option.rect.height() / 2 - radius,
                                           2 * radius, 2 * radius))
            painter.restore()
    
        def sizeHint(self, option, index):
            return QtCore.QSize(self.pixel_size, self.pixel_size)
    
        def setPixelSize(self, size):
            self.pixel_size = size
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self):
            super(MainWindow, self).__init__()
    
            self.model = ImageModel(self)
    
            centralWidget = QtWidgets.QWidget()
    
            self.view = QtWidgets.QTableView()
            self.view.setShowGrid(False)
            self.view.horizontalHeader().hide()
            self.view.verticalHeader().hide()
            self.view.horizontalHeader().setMinimumSectionSize(1)
            self.view.verticalHeader().setMinimumSectionSize(1)
            self.view.horizontalHeader().setDefaultSectionSize(4)
            self.view.verticalHeader().setDefaultSectionSize(4)
            self.view.setModel(self.model)
    
            delegate = PixelDelegate(self)
            self.view.setItemDelegate(delegate)
    
            mainLayout = QtWidgets.QVBoxLayout()
            mainLayout.addWidget(self.view)
            centralWidget.setLayout(mainLayout)
    
            self.setCentralWidget(centralWidget)
            self.setWindowTitle("Pixelator")
            self.resize(self.model.columnCount(), self.model.rowCount())
    
        def updateView(self):
            self.view.resizeColumnsToContents()
            self.view.resizeRowsToContents()
    
    
    if __name__ == '__main__':
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        window = MainWindow()
        window.show()
        sys.exit(app.exec_())
    
    


  • @alom
    Probably completely irrelevant, I haven't looked at the example, but why is your painter.restore() in an else and not correctly paired with the painter.save()? And the drawEllipse() is also else-only? This is Python! Isn't the if else just supposed to be for picking the brush?



  • Ah, Thanks! I had an incorrect indent with :

    painter.drawEllipse(QtCore.QRectF(option.rect.x() + option.rect.width() / 2 - radius,
                                       option.rect.y() + option.rect.height() / 2 - radius,
                                       2 * radius, 2 * radius))
    painter.restore()
    

    Looks like i had to add code below to correctly set my cell size :

    self.view.horizontalHeader().setDefaultSectionSize(4)
    self.view.verticalHeader().setDefaultSectionSize(4)
    

    Yeah, I was just trying to match what the example had,
    I got rid of that unnecessary "else" ...also not why we need to manage the option.state and QtWidgets.QStyle.State_Selected ?
    i remove that and was able to get the black and white image as expected.

    Thanks so much!



  • @alom said in Pixelator example for PySide2:

    I had an incorrect indent with :

    Indeed! And being my non-favorite language of Python, that was the consequence of those few extra whitespaces :)


Log in to reply