Search code examples
pyqt4scrollbars

Adding scrollbar in pyqt4


I have some large images to be inserted in window and my window size is defined. If my image size is greater than window, there must be scroll bars else not. I have also panning and zooming features implemented so that i can resize image to any size. Thanks antiearth for this sample code

from PyQt4 import QtCore, QtGui
import sys

class Annotator(QtGui.QWidget):
def __init__(self):
    QtGui.QWidget.__init__(self)

    self.image = None
    self.scale = 1.0
    self.position = (100, 100)

    self.pressed = None
    self.anchor = None

    self.load('Some LArge Image/Images.png') 

def load(self, filename):
    self.image = QtGui.QImage(filename)

def mousePressEvent(self, event):
    print 'PRESSED : ',event.pos()
    self.pressed = event.pos()
    self.anchor = self.position

def mouseReleaseEvent(self, event):
    self.pressed = None

def mouseMoveEvent(self, event):
    if (self.pressed):
        dx, dy = event.x() - self.pressed.x(), event.y() - self.pressed.y()
        self.position = (self.anchor[0] - dx, self.anchor[1] - dy)
    self.repaint()


def wheelEvent(self, event):
    oldscale = self.scale
    self.scale += event.delta() / 1200.0
    if (self.scale < 0.1):
        self.scale = oldscale

    screenpoint = self.mapFromGlobal(QtGui.QCursor.pos())
    dx, dy = screenpoint.x(), screenpoint.y()
    oldpoint = (screenpoint.x() + self.position[0], screenpoint.y() + self.position[1])
    newpoint = (oldpoint[0] * (self.scale/oldscale),
                oldpoint[1] * (self.scale/oldscale))
    self.position = (newpoint[0] - dx, newpoint[1] - dy)
    self.repaint()

def paintEvent(self, event):
    painter = QtGui.QPainter()
    painter.begin(self)

    painter.drawImage(0, 0,
        self.image.scaled(
            self.image.width() * self.scale,
            self.image.height() * self.scale,
            QtCore.Qt.KeepAspectRatio),
        self.position[0], self.position[1])

    painter.end()

app = QtGui.QApplication(sys.argv)
annotator = Annotator()
annotator.show()
sys.exit(app.exec_())

I want to insert scrollbars here. Hope I made this clear.


Solution

  • In PyQt4 have QtGui.QScrollArea to allow your resize with scroll bars, So your have to implement this class and in your def paintEvent (self, eventQPaintEvent) your have calculate new position and resize your widget with QWidget.setFixedSize (self, QSize)

    Full example;

    from PyQt4 import QtCore, QtGui
    import sys
    
    class Annotator (QtGui.QLabel):
        def __init__(self, parentQExampleScrollArea, parentQWidget = None):
            QtGui.QLabel.__init__(self, parentQWidget)
            self.parentQExampleScrollArea = parentQExampleScrollArea
            self.image = None
            self.scale = 1.0
            self.position = (0, 0)
            self.pressed = None
            self.anchor = None
            self.load('myImage.jpg') 
    
        def load (self, filename):
            self.image = QtGui.QImage(filename)
    
        def mousePressEvent (self, eventQMouseEvent):
            self.pressed = eventQMouseEvent.pos()
            self.anchor = self.position
    
        def mouseReleaseEvent (self, eventQMouseEvent):
            self.pressed = None
    
        def mouseMoveEvent (self, eventQMouseEvent):
            if (self.pressed):
                dx, dy = eventQMouseEvent.x() - self.pressed.x(), eventQMouseEvent.y() - self.pressed.y()
                self.position = (self.anchor[0] - dx, self.anchor[1] - dy)
            self.repaint()
    
        def wheelEvent (self, eventQWheelEvent):
            oldscale = self.scale
            self.scale += eventQWheelEvent.delta() / 1200.0
            if (self.scale < 0.1):
                self.scale = oldscale
            screenpoint = self.mapFromGlobal(QtGui.QCursor.pos())
            dx, dy = screenpoint.x(), screenpoint.y()
            oldpoint = (screenpoint.x() + self.position[0], screenpoint.y() + self.position[1])
            newpoint = (oldpoint[0] * (self.scale/oldscale), oldpoint[1] * (self.scale/oldscale))
            self.position = (newpoint[0] - dx, newpoint[1] - dy)
            self.repaint()
    
        def paintEvent (self, eventQPaintEvent):
            scaledQImage = self.image.scaled (
                self.image.width() * self.scale,
                self.image.height() * self.scale,
                QtCore.Qt.KeepAspectRatio)
            painter = QtGui.QPainter()
            painter.begin(self)
            painter.drawImage (
                0,
                0,
                scaledQImage,
                0 if self.position[0] > 0 else self.position[0],
                0 if self.position[1] > 0 else self.position[1])
            painter.end()
            scaledWidth  = self.parentQExampleScrollArea.size().width() - 16 if self.position[0] > 0 else scaledQImage.width()
            scaledHeight = self.parentQExampleScrollArea.size().height() - 16 if self.position[1] > 0 else scaledQImage.height()
            self.setFixedSize(abs(self.position[0]) + scaledWidth, abs(self.position[1]) + scaledHeight)
    
    class QExampleScrollArea (QtGui.QScrollArea):
        def __init__ (self, parentQWidget = None):
            super(QtGui.QScrollArea, self).__init__(parentQWidget)
            self.myAnnotator = Annotator(self)
            self.setWidget(self.myAnnotator)
    
        def mousePressEvent (self, eventQMouseEvent):
            QtGui.QScrollArea.mousePressEvent(self, eventQMouseEvent)
            self.myAnnotator.mousePressEvent(eventQMouseEvent)
    
        def mouseReleaseEvent (self, eventQMouseEvent):
            QtGui.QScrollArea.mouseReleaseEvent(self, eventQMouseEvent)
            self.myAnnotator.mouseReleaseEvent(eventQMouseEvent)
    
        def mouseMoveEvent (self, eventQMouseEvent):
            QtGui.QScrollArea.mouseMoveEvent(self, eventQMouseEvent)
            self.myAnnotator.mouseMoveEvent(eventQMouseEvent)
    
        def wheelEvent (self, eventQWheelEvent):
            self.myAnnotator.wheelEvent(eventQWheelEvent)
    
    app = QtGui.QApplication(sys.argv)
    myQExampleScrollArea = QExampleScrollArea()
    myQExampleScrollArea.show()
    sys.exit(app.exec_())
    

    Note : Recommend use QtGui.QLabel to paint image