Qt : 종횡비를 유지하면서 QPixmap을 포함하는 QLabel 크기 조정
QLabel을 사용하여 더 크고 동적으로 변경되는 QPixmap의 내용을 사용자에게 표시합니다. 사용 가능한 공간에 따라이 레이블을 더 작게 / 더 크게 만드는 것이 좋습니다. 화면 크기가 항상 QPixmap만큼 크지는 않습니다.
원본 QPixmap의 종횡비를 유지하면서 QPixmap의 크기를 조정하기 위해 QLabel QSizePolicy
과 sizeHint()
의 수정하려면 어떻게 해야합니까?
sizeHint()
QLabel을 수정할 수 없습니다 minimumSize()
. 0으로 설정해도 도움이되지 않습니다. hasScaledContents()
QLabel을 설정 하면 성장이 허용되지만 종횡비가 깨집니다.
QLabel을 서브 클래 싱하는 것이 도움이되었지만이 솔루션은 단순한 문제에 너무 많은 코드를 추가합니다.
서브 클래 싱 없이 이를 수행하는 방법에 대한 현명한 힌트가 있습니까?
레이블 크기를 변경하려면 확장 또는 최소 확장과 같은 레이블에 적절한 크기 정책을 선택할 수 있습니다.
픽스맵이 변경 될 때마다 종횡비를 유지하여 픽스맵의 크기를 조정할 수 있습니다.
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));
이 코드를 추가해야하는 두 곳이 있습니다.
- 픽스맵이 업데이트 될 때
- 에서
resizeEvent
라벨을 포함하는 위젯의
이 누락 된 하위 클래스를 다듬 었습니다 QLabel
. 굉장하고 잘 작동합니다.
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());
}
도움이 되었기를 바랍니다. ( resizeEvent
@dmzl의 답변에 따라 업데이트 됨 )
contentsMargin
가로 세로 비율을 수정하는 데 사용 합니다.
#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);
}
}
지금까지 완벽하게 작동합니다. 천만에요.
phyatt의 AspectRatioPixmapLabel
수업을 사용해 보았지만 몇 가지 문제가 발생했습니다.
- Sometimes my app entered an infinite loop of resize events. I traced this back to the call of
QLabel::setPixmap(...)
inside the resizeEvent method, becauseQLabel
actually callsupdateGeometry
insidesetPixmap
, which may trigger resize events... heightForWidth
seemed to be ignored by the containing widget (aQScrollArea
in my case) until I started setting a size policy for the label, explicitly callingpolicy.setHeightForWidth(true)
- I want the label to never grow more than the original pixmap size
QLabel
's implementation ofminimumSizeHint()
does some magic for labels containing text, but always resets the size policy to the default one, so I had to overwrite it
That 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();
}
}
Thanks for sharing this. Would you have any suggestions on how I can set a "preferred" size to the QPixmap so that it does not take the maximum resolution on the first launch of the application?
'UFO ET IT' 카테고리의 다른 글
FancyBox를 사용하여 인라인 콘텐츠로드 (0) | 2020.11.07 |
---|---|
번들 식별자 및 푸시 인증서… aps-environment 자격 오류 (0) | 2020.11.07 |
중첩 된 파이썬 사전 및 목록에서 모든 키 발생 찾기 (0) | 2020.11.07 |
firstprivate와 lastprivate는 OpenMP의 private 절과 어떻게 다릅니 까? (0) | 2020.11.07 |
새로 고침과 플러시 (0) | 2020.11.07 |