Search code examples
pythonpyqt4

Scribble pad over an image in pyQt4


suppose I want to load an image and scribble on it. But If the image is large then it could not fit into the image viewer. Hence I want a scrollbar. How do I do this?

For example: lets say the image is:

enter image description here

and when i load it into my program it becomes:

enter image description here

Now I want to put it into the scrollbar widget(so that the image can be accessed fully) and the most important thing is I want to make any kind of drawing(scribble) on it. How do I do this using PyQt4? Is there any python code available for that?


Solution

  • If you want to place an image with QScrollbar a possible option is to use QScrollArea, but if you indicate that you want to draw the correct thing is to use QGraphicsView since it allows you to add items. For example to make the scribble you could use QGraphicsPathItem and for the image QGraphicsPixmapItem as I show below:

    from PyQt4 import QtCore, QtGui
    
    class ScribbleView(QtGui.QGraphicsView):
        def __init__(self, parent=None):
            super(ScribbleView, self).__init__(parent)
            self.setScene(QtGui.QGraphicsScene(self))
            self._image_item = QtGui.QGraphicsPixmapItem()
            self.scene().addItem(self._image_item)
            self.initial_path()
    
        def initial_path(self):
            self._path = QtGui.QPainterPath()
            pen = QtGui.QPen(QtGui.QColor("green"), 4, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap)
            self._path_item = self.scene().addPath(self._path, pen)
    
        @QtCore.pyqtSlot()
        def load_image(self):
            filename = QtGui.QFileDialog.getOpenFileName(self, 
                "Open Image", QtCore.QDir.currentPath(), 
                "Image Files (*.png *.jpg *.bmp)")
            if filename:
                self._image_item.setPixmap(QtGui.QPixmap(filename))
    
        def mousePressEvent(self, event):
            if not self._image_item.pixmap().isNull():
                self._path.moveTo(self.mapToScene(event.pos()))
                self._path_item.setPath(self._path)
            super(ScribbleView, self).mousePressEvent(event)
    
        def mouseMoveEvent(self, event):
            if not self._image_item.pixmap().isNull():
                self._path.lineTo(self.mapToScene(event.pos()))
                self._path_item.setPath(self._path)
            super(ScribbleView, self).mousePressEvent(event)
    
        def mouseReleaseEvent(self, event):
            if not self._image_item.pixmap().isNull():
                self._path.lineTo(self.mapToScene(event.pos()))
                self._path_item.setPath(self._path)       
                self.initial_path()
            super(ScribbleView, self).mouseReleaseEvent(event)
    
    class ScribbleWidget(QtGui.QMainWindow):
        def __init__(self, parent=None):
            super(ScribbleWidget, self).__init__(parent)
            view = ScribbleView()
            self.setCentralWidget(view)
            menubar = self.menuBar()
            file_menu = menubar.addMenu("&File")
            image_action = file_menu.addAction("Load Image")
            image_action.triggered.connect(view.load_image)
    
    if __name__ == '__main__':
        import sys
        app = QtGui.QApplication(sys.argv)
        w = ScribbleWidget()
        w.resize(640, 480)
        w.show()
        sys.exit(app.exec_())
    

    enter image description here