Ich verwende ein QLabel, um dem Benutzer den Inhalt einer größeren, sich dynamisch ändernden QPixmap anzuzeigen. Es wäre schön, dieses Etikett je nach verfügbarem Platz kleiner/größer zu gestalten. Die Bildschirmgröße ist nicht immer so groß wie die QPixmap.
Wie kann ich die QSizePolicy
und sizeHint()
des QLabel ändern, um die Größe der QPixmap zu ändern, während das Seitenverhältnis der ursprünglichen QPixmap beibehalten wird?
Ich kann sizeHint()
des QLabels nicht ändern, und es hilft nicht, minimumSize()
auf Null zu setzen. Das Setzen von hasScaledContents()
auf dem QLabel ermöglicht das Wachsen, unterbricht aber das Seitenverhältnis ...
QLabel-Unterklassen haben geholfen, aber diese Lösung fügt zu viel Code für ein einfaches Problem hinzu ...
Irgendwelche klugen Hinweise, wie man dies bewerkstelligt ohne Unterklassen?
Um die Etikettengröße zu ändern, können Sie eine geeignete Größenrichtlinie für das Etikett auswählen, z. B. Erweitern oder Minimalerweiterung.
Sie können die Pixmap skalieren, indem Sie bei jeder Änderung das Seitenverhältnis beibehalten:
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));
Es gibt zwei Stellen, an denen Sie diesen Code hinzufügen sollten:
resizeEvent
des Widgets, das die Bezeichnung enthältIch habe diese fehlende Unterklasse von QLabel
aufpoliert. Es ist großartig und funktioniert gut.
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());
}
Hoffentlich hilft das! (Aktualisiert resizeEvent
, per @ dmzls Antwort)
Ich benutze nur contentsMargin
, um das Seitenverhältnis festzulegen.
#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);
}
}
Funktioniert soweit perfekt für mich. Bitte.
Ich habe versucht, die Klasse AspectRatioPixmapLabel
von phyatt zu verwenden, hatte jedoch einige Probleme:
QLabel::setPixmap(...)
innerhalb der resizeEvent-Methode zurückgeführt, da QLabel
tatsächlich updateGeometry
innerhalb von setPixmap
aufruft, was Größenänderungsereignisse auslösen kann. .heightForWidth
schien vom enthaltenen Widget ignoriert zu werden (in meinem Fall ein QScrollArea
), bis ich begann, eine Größenrichtlinie für das Etikett festzulegen, indem ich policy.setHeightForWidth(true)
explizit aufrief.QLabel
's Implementierung von minimumSizeHint()
bewirkt eine gewisse Magie für Beschriftungen, die Text enthalten, setzt jedoch die Größenrichtlinie immer auf die Standardrichtlinie zurück, sodass ich sie überschreiben mussteDas heißt, hier ist meine Lösung. Ich stellte fest, dass ich einfach setScaledContents(true)
verwenden und QLabel
die Größenänderung vornehmen konnte. Dies hängt natürlich davon ab, welches Widget/Layout das heightForWidth
enthält.
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();
}
}
Vielen Dank für das Teilen. Haben Sie Vorschläge, wie ich eine "bevorzugte" Größe für die QPixmap festlegen kann, damit diese beim ersten Start der Anwendung nicht die maximale Auflösung annimmt?