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)