Search code examples
pythonpyqtpyqt5python-3.6qgraphicsitem

QGraphicsRectItem set image crashes


I am investigating how to set a map image into a QGraphicsRectItem object within a QGraphicsScene object, and I get a clean crash in PyQT5.

The code is:

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import smopy
from PIL.ImageQt import ImageQt


class MapWidget(QGraphicsRectItem):

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

        self.setRect(0.0, 0.0, 800, 600)
        self.setFlags(self.ItemIsSelectable | self.ItemIsMovable)
        self.image = None

        # get map
        map = smopy.Map((42., -1., 53., 3.), z=11, tilesize=48)
        img = ImageQt(map.img)
        self.image = QPixmap.fromImage(img)

    def paint(self, painter, option, widget=None):
        painter.drawPixmap(QPoint(0, 0), self.image)


class Window(QDialog):

    def __init__(self):
        super(Window, self).__init__()

        self.layout = QVBoxLayout(self)

        self.view = QGraphicsView()

        self.scene = QGraphicsScene()

        self.view.setScene(self.scene)

        self.layout.addWidget(self.view)

        self.map = MapWidget()

        self.scene.addItem(self.map)

        self.resize(1200, 800)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

The output message is:

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)


Solution

  • Instead of converting it to PIL, it can be converted to numpy and loaded to QImage. On the other hand, it is better to use QGraphicsPixmapItem because it repaints correctly.

    import sys
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    import smopy
    
    
    class MapWidget(QGraphicsPixmapItem):
        def __init__(self, parent=None):
            super(MapWidget, self).__init__(parent)
            self.setFlags(self.ItemIsSelectable | self.ItemIsMovable)
    
            # get map
            map = smopy.Map((42., -1., 53., 3.), z=11, tilesize=48)
            numpy_image= map.to_numpy()
            img = QImage(numpy_image.data, *numpy_image.shape[1::-1], QImage.Format_RGB888)
            self.setPixmap(QPixmap.fromImage(img))
    
    class Window(QDialog):
        def __init__(self):
            super(Window, self).__init__()
    
            self.layout = QVBoxLayout(self)
            self.view = QGraphicsView()
            self.scene = QGraphicsScene()
            self.view.setScene(self.scene)
    
            self.layout.addWidget(self.view)
    
            self.map = MapWidget()
            self.scene.addItem(self.map)
            self.resize(1200, 800)
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        window = Window()
        window.show()
        sys.exit(app.exec_())
    

    enter image description here