Skip to content
Advertisement

Scrollbars Do Not Appear in PyQt5 Custom Label

A few months ago I wanted to know how to draw on an image (Insert Image into QGridLayout and Draw on top of image in PyQt5). Eyllanesc very kindly gave me a complete solution. I now would like to have this image widget scrollable so I can enlarge it. Howerver, when I add a scroll area the scrollbars do not appear. When I do force the scrollbars to appear, they do not seem to be attached to anything. I’ve looked at a number of posts on Scroll Areas: /45515445/, /6792862/, /55149412/, /23446855/, /46979944/, /46024724/, /53843836/, /11886908/, /53914267/, /53843836/, /45515445/, /52671838/. These solutions are not in a QGridLayout, but I don’t know if this is the source of my problem or not. Could anyone help me? Thank you!

from PyQt5.QtCore import (QPoint, Qt)
from PyQt5.QtGui import (QPainter, QPen, QPixmap)
from PyQt5.QtWidgets import (QApplication, QGridLayout, QMainWindow, QPushButton, QScrollArea, QTextEdit, QWidget) ####NEW
import os; import sys
###########################################################################
# https://stackoverflow.com/questions/56194201
class ImageLabel(QWidget):
# loads a graphic file, inserts it into a QLabel that allows drawing of lines on the surface
    def __init__(self, parent=None):
        super(ImageLabel, self).__init__(parent)
        self.image = QPixmap('image.png')
        self.drawing = False
        self.lastPoint = QPoint()

    def changePixmap(self,img, x, y):
        self.image = QPixmap(img).scaled(x, y, Qt.KeepAspectRatio)  #/34213021/, /21802868/
        self.repaint()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawPixmap(QPoint(), self.image)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.drawing = True
            self.lastPoint = event.pos()

    def mouseMoveEvent(self, event):
        if (event.buttons() & Qt.LeftButton) and self.drawing:
            painter = QPainter(self.image)
            painter.setPen(QPen(Qt.red, 1, Qt.SolidLine))
            painter.drawLine(self.lastPoint, event.pos())
            self.lastPoint = event.pos()
            self.update()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.drawing = False

    def sizeHint(self):
        return self.image.size()
###########################################################################
class MainWindow(QMainWindow):
#########################################
    def ZoomIn(self):
        self.width = self.ilabel.image.size().width() *1.25
        self.height = self.ilabel.image.size().height() * 1.25
        self.ilabel.changePixmap('image.png', self.width, self.height)# SOF: /24106903/
########################################
    def ZoomOut(self):
        self.width = self.ilabel.image.size().width() /  1.25
        self.height = self.ilabel.image.size().height() / 1.25
        self.ilabel.changePixmap('image.png', self.width, self.height)# SOF: /24106903/
########################################
    def __init__(self, parent = None):
        super().__init__(parent)
# Set up main widget
        widget = QWidget()
        self.setCentralWidget(widget)
        self.myLayout = QGridLayout(widget)
# Image
#######
        self.width = 564; self.height = 800
        self.ilabel = ImageLabel()

# https://stackoverflow.com/questions/45515445/
# Add this custom label to a scroll area
        self.scroller = QScrollArea(self)
        self.scroller.setWidget(self.ilabel)
        self.scroller.setWidgetResizable(True)
        self.scroller.adjustSize()
        self.myLayout.addWidget(self.scroller, 0, 0, 110, 70)

# PROBLEM: NO SCROLLBARS APPEAR!
# If I add:
        self.scroller.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) #https://stackoverflow.com/questions/53914267/
        self.scroller.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) # https://stackoverflow.com/questions/53914267/
# The scrollbars appear but do not scroll the image. I imagine they are not actually atached to the scroll area

# ZoomIn button
        self.btnzi = QPushButton('Zoom In',self)
        self.btnzi.clicked.connect(self.ZoomIn)
        self.myLayout.addWidget(self.btnzi, 112, 5, 1, 1)
# ZoomOut button
        self.btnzo = QPushButton('Zoom Out',self)
        self.btnzo.clicked.connect(self.ZoomOut)
        self.myLayout.addWidget(self.btnzo, 112, 10, 1, 1)
# Text
######
        self.textedit = QTextEdit()
        self.myLayout.addWidget(self.textedit, 0, 70, 111, 100)

if __name__ =='__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
###########################################################################

Advertisement

Answer

QScrollArea uses size() and minimumSizeHint() to set when the scrollbar is needed, so in your case it is fixed and does not depend on the size of the image which causes the problem.

class ImageLabel(QWidget):
    # ...
    def changePixmap(self,img, x, y):
        self.image = QPixmap(img).scaled(x, y, Qt.KeepAspectRatio)  #/34213021/, /21802868/
        self.update()
        self.resize(self.image.size())

    def sizeHint(self):
        return self.image.size()

    def minimumSizeHint(self):
        return self.sizeHint()

It is also not necessary to force the appearance of the scrollbar so you must remove:

self.scroller.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroller.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement