Issue
I'm trying to learn it by re-making an old command line C program I've got for working with pixel art.
At the moment, the main window starts as a single QLabel set to show a 300 x 300 scaled up version of a 10 x 10 white image.
I'm using the resizeEvent (I've also tried using paintEvent with the same problem) to rescale the image to fill the window as the window size is increased.
My question is, how do I rescale the image to fit in the window as the window size is decreased? As it stands, the window can't be resized smaller than the widget displaying the image. Essentially, I can make the window (and image) bigger, but never smaller.
My code for this so far is below. As it stands it's only working based on changes to window width, just to keep it simple while I'm working this out. Is there a way to allow the window to be resized to be smaller than the largest widget? Or is there a better way to approach this problem?
#Create white 10*10 image
image = QImage(10,10,QImage.Format.Format_ARGB32)
image_scaled = QImage()
image.fill(QColor(255,255,255))
class Window(QMainWindow):
#scale image to change in window width (image is window width * window width square)
def resizeEvent(self,event):
if self.imageLabel.width()>self.imageLabel.height():
self.image_scaled = image.scaled(self.imageLabel.width(),self.imageLabel.width())
self.pixmap = QPixmap.fromImage(self.image_scaled)
self.imageLabel.setPixmap(self.pixmap)
QWidget.resizeEvent(self, event)
def __init__(self, parent=None):
super().__init__(parent)
self.setGeometry(100,100,300,300)
self.imageLabel = QLabel()
self.setCentralWidget(self.imageLabel)
self.image_scaled = image.scaled(self.imageLabel.width(),self.imageLabel.width())
self.pixmap = QPixmap.fromImage(self.image_scaled)
self.imageLabel.setPixmap(self.pixmap)
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
Solution
While the OP proposed solution might work, it has an important drawback: it uses a QScrollArea for the wrong purpose (since it's never used for scrolling). That approach creates unnecessary overhead while resizing, as the view will need to compute lots of things about its contents before "finishing" the resize event (including scroll bar ranges and geometries) that, in the end, will never be actually used.
The main problem comes from the fact that QLabel doesn't allow resizing to a size smaller than the original pixmap set. To work around this issue, the simplest solution is to create a custom QWidget subclass that draws the pixmap on its own.
class ImageViewer(QWidget):
pixmap = None
_sizeHint = QSize()
ratio = Qt.KeepAspectRatio
transformation = Qt.SmoothTransformation
def __init__(self, pixmap=None):
super().__init__()
self.setPixmap(pixmap)
def setPixmap(self, pixmap):
if self.pixmap != pixmap:
self.pixmap = pixmap
if isinstance(pixmap, QPixmap):
self._sizeHint = pixmap.size()
else:
self._sizeHint = QSize()
self.updateGeometry()
self.updateScaled()
def setAspectRatio(self, ratio):
if self.ratio != ratio:
self.ratio = ratio
self.updateScaled()
def setTransformation(self, transformation):
if self.transformation != transformation:
self.transformation = transformation
self.updateScaled()
def updateScaled(self):
if self.pixmap:
self.scaled = self.pixmap.scaled(self.size(), self.ratio, self.transformation)
self.update()
def sizeHint(self):
return self._sizeHint
def resizeEvent(self, event):
self.updateScaled()
def paintEvent(self, event):
if not self.pixmap:
return
qp = QPainter(self)
r = self.scaled.rect()
r.moveCenter(self.rect().center())
qp.drawPixmap(r, self.scaled)
class Window(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.imageLabel = ImageViewer(QPixmap.fromImage(image))
self.setCentralWidget(self.imageLabel)
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.