QLabelを使用して、大きく、動的に変化するQPixmapのコンテンツをユーザーに表示します。使用可能なスペースに応じて、このラベルを小さく/大きくするとよいでしょう。画面サイズは、常にQPixmapほど大きくはありません。
QLabelのQSizePolicy
とsizeHint()
を変更して、元のQPixmapのアスペクト比を維持しながらQPixmapのサイズを変更するにはどうすればよいですか?
QLabelのsizeHint()
を変更することはできません。minimumSize()
をゼロに設定しても役に立ちません。 QLabelでhasScaledContents()
を設定すると成長が可能になりますが、アスペクト比が壊れます...
QLabelのサブクラス化は役立ちましたが、この解決策は単純な問題に対してあまりにも多くのコードを追加します...
これを達成するためのスマートなヒントwithoutサブクラス化?
ラベルサイズを変更するには、エキスパンドや最小エキスパンドなど、ラベルの適切なサイズポリシーを選択できます。
変更するたびにアスペクト比を維持することにより、ピックスマップをスケーリングできます。
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));
このコードを追加する必要がある2つの場所があります。
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());
}
お役に立てば幸いです! (@dmzlの回答ごとにresizeEvent
を更新)
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
クラスを使用してみましたが、いくつかの問題が発生しました。
QLabel
が実際にupdateGeometry
内でsetPixmap
を呼び出すため、resizeEventメソッド内のQLabel::setPixmap(...)
の呼び出しに遡ります。 。heightForWidth
は、明示的にpolicy.setHeightForWidth(true)
を呼び出してラベルのサイズポリシーの設定を開始するまで、含まれるウィジェット(私の場合はQScrollArea
)によって無視されたようです。QLabel
のminimumSizeHint()
の実装は、テキストを含むラベルに対していくつかの魔法を行いますが、サイズポリシーを常にデフォルトのポリシーにリセットするため、上書きする必要がありました。とはいえ、ここに私の解決策があります。 setScaledContents(true)
を使用して、QLabel
でサイズ変更を処理できることがわかりました。もちろん、これは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();
}
}
これを共有してくれてありがとう。アプリケーションの最初の起動時に最大解像度を取得しないようにQPixmapに「優先」サイズを設定する方法について何か提案がありますか?