Qt: Resizing a Qlabel Containing a Qpixmap While Keeping Its Aspect Ratio

Qt: resizing a QLabel containing a QPixmap while keeping its aspect ratio

In order to change the label size you can select an appropriate size policy for the label like expanding or minimum expanding.

You can scale the pixmap by keeping its aspect ratio every time it changes:

QPixmap p; // load pixmap
// get label dimensions
int w = label->width();
int h = label->height();

// set a scaled pixmap to a w x h window keeping its aspect ratio
label->setPixmap(p.scaled(w,h,Qt::KeepAspectRatio));

There are two places where you should add this code:

  • When the pixmap is updated
  • In the resizeEvent of the widget that contains the label

How to resize child QLabel (having a QPixmap) with QHBLayout keeping aspect ratio?

Try using the subclass of QLabel listed here:

https://stackoverflow.com/a/22618496/999943

Hope that helps.

Keep aspect ratio of image in a QLabel whilst resizing window

You firstly need to change the layout so that it uses alignment rather than expanding spacers to keep the label at the top left corner. Also, some properties of the label need adjustment so that it can resize itself freely. This can all be done in Qt Designer, but your example code can also be fixed manually like this:

self.LogoLabel = QtWidgets.QLabel(self.centralwidget)
self.LogoLabel.setText("")
self.LogoLabel.setObjectName("LogoLabel")

# new stuff
self.LogoLabel.setScaledContents(False)
self.LogoLabel.setMinimumSize(1, 1)
self.LogoLabel.setSizePolicy(
QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
self.LogoLabel.setAlignment(QtCore.Qt.AlignTop)
self.verticalLayout_3.setAlignment(QtCore.Qt.AlignTop)

self.verticalLayout_3.addWidget(self.LogoLabel)

The dynamic resizing can then be handled using an event-filter, like this:

class Test(QtWidgets.QMainWindow, Ui_ZEBRA):
def __init__(self, parent=None):
super(Test, self).__init__(parent)
self.setupUi(self)
self._logo = QtGui.QPixmap('res/image.png')
self.LogoLabel.setPixmap(self._logo)
self.LogoLabel.installEventFilter(self)

def eventFilter(self, widget, event):
if event.type() == QtCore.QEvent.Resize and widget is self.LogoLabel:
self.LogoLabel.setPixmap(self._logo.scaled(
self.LogoLabel.width(), self.LogoLabel.height(),
QtCore.Qt.KeepAspectRatio))
return True
return super(Test, self).eventFilter(widget, event)

Display image in Qt to fit label size

Does QLabel::setScaledContents(bool) help? There may also be some useful information in the image viewer example too.

Qt - QLabel won't resize with fixed ratio

A possible solution is to install an eventFilter to the centralwidget so doing the required calculation is set the size.

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->centralWidget->installEventFilter(this);
ui->imageLabel->setPixmap(QPixmap(":/image.png"));
ui->imageLabel->setScaledContents(true);
}

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
const float ratio = 1.25;
if(watched == ui->centralWidget && event->type() == QEvent::Resize
&& ui->centralWidget->width() > 0
&& ui->centralWidget->height() > 0){
float central_ratio = 1.0*ui->centralWidget->width()/ui->centralWidget->height(); QSize s;
if(central_ratio > ratio){
s = QSize(ratio*ui->centralWidget->height(), ui->centralWidget->height());
}
else{
s = QSize(ui->centralWidget->width(), ui->centralWidget->width()/ratio);
}
ui->imageLabel->resize(s);
}
return QMainWindow::eventFilter(watched, event);
}

How to Autoresize QLabel pixmap keeping ratio without using classes?

There are a couple of ways to do this.

Firstly, you can promote your QLabel in Qt Designer to a custom subclass that is written in python. Right-click the QLabel and select "Promote to...", then give the class a name (e.g. "ScaledLabel") and set the header file to the python module that the custom subclass class will be imported from (e.g. 'mylib.classes').

The custom subclass would then re-implement the resizeEvent like this:

class ScaledLabel(QtGui.QLabel):
def __init__(self, *args, **kwargs):
QtGui.QLabel.__init__(self)
self._pixmap = QtGui.QPixmap(self.pixmap())

def resizeEvent(self, event):
self.setPixmap(self._pixmap.scaled(
self.width(), self.height(),
QtCore.Qt.KeepAspectRatio))

For this to work properly, the QLabel should have its size policy set to expanding or minimumExpanding, and the minimum size should be set to a small, non-zero value (so the image can be scaled down).

The second method avoids using a subclass and uses an event-filter to handle the resize events:

class MainWindow(QtGui.QMainWindow):
def __init__(self):
...
self._pixmap = QtGui.QPixmap(self.label.pixmap())
self.label.installEventFilter(self)

def eventFilter(self, widget, event):
if (event.type() == QtCore.QEvent.Resize and
widget is self.label):
self.label.setPixmap(self._pixmap.scaled(
self.label.width(), self.label.height(),
QtCore.Qt.KeepAspectRatio))
return True
return QtGui.QMainWindow.eventFilter(self, widget, event)

Resizable PyQt widget displaying an image with fixed aspect ratio

The following QLabel-based widget that will preserve the aspect ratio of a pixmap assigned to it. It uses the heighForWidth method to return the preferred height of the widget given its width. This way, the widget naturally respects the aspect ratio of the pixmap when resized and scales it accordingly. Tested in PyQt5.

class ImageWidget(QLabel):

def __init__(self, parent=None):
super().__init__(parent)
self.setScaledContents(True)

def hasHeightForWidth(self):
return self.pixmap() is not None

def heightForWidth(self, w):
if self.pixmap():
return int(w * (self.pixmap().height() / self.pixmap().width()))

PyQt Keeping QLabel Size Aspect Ratio

I seem to have cracked it, so incase anyone else was wondering how to do this:

I took tmoreau's solution and modified it slightly. For it to work, you need to set the QLabel's maximum size to the image's new size prior to the paint event. Immediately afterwards, you need to set the maximum size for the QLabel to something very large, otherwise, you will not be able to enlarge the image at all as you will have specified the maximum size to be that of the current image.

def paintEvent(self, event):
size = self.size()
painter = QtGui.QPainter(self)
point = QtCore.QPoint(0,0)
scaledPix = self.pixmap.scaled(size, Qt.KeepAspectRatio, transformMode = Qt.SmoothTransformation)
self.setMaximumSize(scaledPix.size())
point.setX(0)
point.setY(0)
#print (point.x(), ' ', point.y())
painter.drawPixmap(point, scaledPix)
self.setMaximumSize(QtCore.QSize(4000,5000))

If anyone has a better solution, by all means please let me know!



Related Topics



Leave a reply



Submit