Reputation: 4369
The main window of my PyQt5 application is set up with a text label along the top above a custom canvas widget which displays an image:
from PyQt5 import QtCore, QtGui, QtWidgets
class Canvas(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.image = None
def paintEvent(self, event):
qp = QtGui.QPainter(self)
if self.image:
qp.drawImage(0, 0, self.image)
class Window(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.canvas = Canvas()
self.label = QtWidgets.QLabel()
self.label.setText('foobar')
self.label.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Fixed)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.canvas)
layout.setSpacing(0)
layout.setContentsMargins(0, 0, 0, 0)
content = QtWidgets.QWidget()
content.setLayout(layout)
self.setCentralWidget(content)
self.load_image('a.jpg')
def load_image(self, filename):
image = QtGui.QImage(filename)
self.canvas.image = image
self.canvas.setFixedSize(image.width(), image.height())
self.update()
def keyPressEvent(self, event):
self.load_image('b.jpg')
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
This looks like this, which is what I want:
When the canvas changes to display a smaller image, I want to shrink the window to fit accordingly. However, it looks like this:
It seems that the minimum size that I can give the window if I manually drag to resize it is the size that fits the contents, but why isn't it resizing to this automatically?
Upvotes: 1
Views: 843
Reputation: 244311
When a fixed size is set, it is used as sizeHint, and the latter is used by layouts to set the widget size. So the size of the canvas depends on the size of the widget, but you want the opposite. You must scale the image size to the window size:
from PyQt5 import QtCore, QtGui, QtWidgets
class Canvas(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setSizePolicy(
QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding
)
self.image = QtGui.QImage()
@property
def image(self):
return self._image
@image.setter
def image(self, image):
self._image = image
self.update()
def paintEvent(self, event):
qp = QtGui.QPainter(self)
if not self.image.isNull():
image = self.image.scaled(
self.size(), QtCore.Qt.IgnoreAspectRatio, QtCore.Qt.SmoothTransformation
)
qp.drawImage(0, 0, image)
class Window(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.canvas = Canvas()
self.label = QtWidgets.QLabel("foobar")
self.label.setSizePolicy(
QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed
)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.canvas)
layout.setSpacing(0)
layout.setContentsMargins(0, 0, 0, 0)
content = QtWidgets.QWidget()
content.setLayout(layout)
self.setCentralWidget(content)
self.load_image("a.jpg")
def load_image(self, filename):
image = QtGui.QImage(filename)
self.canvas.image = image
def keyPressEvent(self, event):
self.load_image('b.jpg')
super().keyPressEvent(event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
Upvotes: 2