I tried using phyatt's AspectRatioPixmapLabel
class, but experienced a few problems:
QLabel::setPixmap(...)
inside the resizeEvent method, because QLabel
actually calls updateGeometry
inside setPixmap
, which may trigger resize events...heightForWidth
seemed to be ignored by the containing widget (a QScrollArea
in my case) until I started setting a size policy for the label, explicitly calling policy.setHeightForWidth(true)
QLabel
's implementation of minimumSizeHint()
does some magic for labels containing text, but always resets the size policy to the default one, so I had to overwrite itThat said, here is my solution. I found that I could just use setScaledContents(true)
and let QLabel
handle the resizing.
Of course, this depends on the containing widget / layout honoring the heightForWidth
.
aspectratiopixmaplabel.h
#ifndef ASPECTRATIOPIXMAPLABEL_H
#define ASPECTRATIOPIXMAPLABEL_H
#include <QLabel>
#include <QPixmap>
class AspectRatioPixmapLabel : public QLabel
{
Q_OBJECT
public:
explicit AspectRatioPixmapLabel(const QPixmap &pixmap, QWidget *parent = 0);
virtual int heightForWidth(int width) const;
virtual bool hasHeightForWidth() { return true; }
virtual QSize sizeHint() const { return pixmap()->size(); }
virtual QSize minimumSizeHint() const { return QSize(0, 0); }
};
#endif // ASPECTRATIOPIXMAPLABEL_H
aspectratiopixmaplabel.cpp
#include "aspectratiopixmaplabel.h"
AspectRatioPixmapLabel::AspectRatioPixmapLabel(const QPixmap &pixmap, QWidget *parent) :
QLabel(parent)
{
QLabel::setPixmap(pixmap);
setScaledContents(true);
QSizePolicy policy(QSizePolicy::Maximum, QSizePolicy::Maximum);
policy.setHeightForWidth(true);
this->setSizePolicy(policy);
}
int AspectRatioPixmapLabel::heightForWidth(int width) const
{
if (width > pixmap()->width()) {
return pixmap()->height();
} else {
return ((qreal)pixmap()->height()*width)/pixmap()->width();
}
}