J'utilise un QLabel pour afficher le contenu d'un QPixmap de plus grande taille et qui change de manière dynamique pour l'utilisateur. Il serait bien de rendre cette étiquette plus petite/plus grande en fonction de l'espace disponible. La taille de l'écran n'est pas toujours aussi grande que celle du QPixmap.
Comment puis-je modifier les QSizePolicy
et sizeHint()
du QLabel pour redimensionner le QPixmap tout en conservant le rapport de format du QPixmap d'origine?
Je ne peux pas modifier sizeHint()
du QLabel, régler le minimumSize()
sur zéro n'aide pas. La définition de hasScaledContents()
sur le QLabel permet de développer, mais casse le ratio d'aspect ...
Sous-classer QLabel a aidé, mais cette solution ajoute trop de code pour un simple problème ...
Des astuces astucieuses pour accomplir ceci sans sous-classement?
Afin de changer la taille de l'étiquette, vous pouvez sélectionner une stratégie de taille appropriée pour l'étiquette, telle que l'extension ou l'extension minimale.
Vous pouvez redimensionner la pixmap en conservant ses proportions à chaque changement:
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));
Il y a deux endroits où vous devriez ajouter ce code:
resizeEvent
du widget qui contient l'étiquetteJ'ai poli cette sous-classe manquante de QLabel
. C'est génial et ça marche bien.
aspectratiopixmaplabel.h
#ifndef ASPECTRATIOPIXMAPLABEL_H
#define ASPECTRATIOPIXMAPLABEL_H
#include <QLabel>
#include <QPixmap>
#include <QResizeEvent>
class AspectRatioPixmapLabel : public QLabel
{
Q_OBJECT
public:
explicit AspectRatioPixmapLabel(QWidget *parent = 0);
virtual int heightForWidth( int width ) const;
virtual QSize sizeHint() const;
QPixmap scaledPixmap() const;
public slots:
void setPixmap ( const QPixmap & );
void resizeEvent(QResizeEvent *);
private:
QPixmap pix;
};
#endif // ASPECTRATIOPIXMAPLABEL_H
aspectratiopixmaplabel.cpp
#include "aspectratiopixmaplabel.h"
//#include <QDebug>
AspectRatioPixmapLabel::AspectRatioPixmapLabel(QWidget *parent) :
QLabel(parent)
{
this->setMinimumSize(1,1);
setScaledContents(false);
}
void AspectRatioPixmapLabel::setPixmap ( const QPixmap & p)
{
pix = p;
QLabel::setPixmap(scaledPixmap());
}
int AspectRatioPixmapLabel::heightForWidth( int width ) const
{
return pix.isNull() ? this->height() : ((qreal)pix.height()*width)/pix.width();
}
QSize AspectRatioPixmapLabel::sizeHint() const
{
int w = this->width();
return QSize( w, heightForWidth(w) );
}
QPixmap AspectRatioPixmapLabel::scaledPixmap() const
{
return pix.scaled(this->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
void AspectRatioPixmapLabel::resizeEvent(QResizeEvent * e)
{
if(!pix.isNull())
QLabel::setPixmap(scaledPixmap());
}
J'espère que ça t'as aidé! (Mise à jour resizeEvent
, réponse de @ dmzl)
Je viens d'utiliser contentsMargin
pour corriger les proportions.
#pragma once
#include <QLabel>
class AspectRatioLabel : public QLabel
{
public:
explicit AspectRatioLabel(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
~AspectRatioLabel();
public slots:
void setPixmap(const QPixmap& pm);
protected:
void resizeEvent(QResizeEvent* event) override;
private:
void updateMargins();
int pixmapWidth = 0;
int pixmapHeight = 0;
};
#include "AspectRatioLabel.h"
AspectRatioLabel::AspectRatioLabel(QWidget* parent, Qt::WindowFlags f) : QLabel(parent, f)
{
}
AspectRatioLabel::~AspectRatioLabel()
{
}
void AspectRatioLabel::setPixmap(const QPixmap& pm)
{
pixmapWidth = pm.width();
pixmapHeight = pm.height();
updateMargins();
QLabel::setPixmap(pm);
}
void AspectRatioLabel::resizeEvent(QResizeEvent* event)
{
updateMargins();
QLabel::resizeEvent(event);
}
void AspectRatioLabel::updateMargins()
{
if (pixmapWidth <= 0 || pixmapHeight <= 0)
return;
int w = this->width();
int h = this->height();
if (w <= 0 || h <= 0)
return;
if (w * pixmapHeight > h * pixmapWidth)
{
int m = (w - (pixmapWidth * h / pixmapHeight)) / 2;
setContentsMargins(m, 0, m, 0);
}
else
{
int m = (h - (pixmapHeight * w / pixmapWidth)) / 2;
setContentsMargins(0, m, 0, m);
}
}
Fonctionne parfaitement pour moi jusqu'à présent. De rien.
J'ai essayé d'utiliser la classe AspectRatioPixmapLabel
de phyatt, mais j'ai rencontré quelques problèmes:
QLabel::setPixmap(...)
dans la méthode resizeEvent, car QLabel
appelle en fait updateGeometry
à l'intérieur setPixmap
, ce qui peut déclencher des événements de redimensionnement ...heightForWidth
semblait être ignoré par le widget qui le contenait (un QScrollArea
dans mon cas) jusqu'à ce que je commence à définir une politique de taille pour l'étiquette, appelant explicitement policy.setHeightForWidth(true)
minimumSizeHint()
par QLabel
fait de la magie pour les étiquettes contenant du texte, mais remet toujours la politique de taille à celle par défaut, je devais donc l'écraserCeci dit, voici ma solution. J'ai découvert que je pouvais simplement utiliser setScaledContents(true)
et laisser QLabel
gérer le redimensionnement. Bien entendu, cela dépend du widget/de la mise en page qui respecte le 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();
}
}
Merci de partager cela. Avez-vous des suggestions sur la manière de définir une taille "préférée" pour le QPixmap afin qu'il ne prenne pas la résolution maximale lors du premier lancement de l'application?