web-dev-qa-db-ja.com

ラベルサイズに合わせてQtで画像を表示する

フォームに画像を表示する方法をいくつか試しましたが、どれも私が思うように動作しません。

ラベルを作成し、それを使用して画像を表示するのが最も簡単な方法を多くの場所で読みました。レイアウトで指定されたラベルがありますが、ピックスマップでイメージをロードすると、ラベルはイメージのサイズに変更されます。 imgタグをテキストまたはcss背景プロパティとして使用すると、画像全体が表示されません。私がやりたいのは、ラベルのサイズを変更せずに画像を読み込んでラベルに収まることですが、ウィンドウのサイズを変更すると、ラベルもサイズ変更することで、画像も常に収まるようにサイズを変更する必要がありますそれに。

唯一の方法がラベルのサイズを取得し、それが収まるようにピックスマップのサイズを変更し、サイズ変更イベント(信号)を処理する場合、どのようにピックスマップのサイズを変更できますか?すべてをQImageに保存し、毎回それからピックスマップを作成する必要がないことを願っています。

また、どのように中央に配置できますか?幅と高さの両方に収まらない場合は、小さい方の寸法を中央に配置してください。

ああ、スライダーを使ってオーバーフローを処理したくありません。

27

QLabel :: setScaledContents(bool) は役立ちますか? image viewer example にも有用な情報があるかもしれません。

19
Arnold Spence

実際、この問題には非常に簡単な解決策があります。変更する必要があるものは2つあります。

  1. スケーリングされたコンテンツをtrueに設定します(上記)
  2. ラベルのサイズポリシーを無視に設定します

    QLabel lblImage;
    
    lblImage->setPixmap( QPixmap( "big_image.jpg" ) );
    
    lblImage->setScaledContents( true );
    
    lblImage->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored );
    

LblImageが自動的にサイズ変更されている場合、画像はラベルのサイズまで伸縮します。

19
bukkfa

私も自分の質問に答えますが、上記の簡単なものをリクエストしたため、解決策としてマークしません。結局、あまりにも単純ではないソリューションを使用することになったので、同様のことをする必要があり、それで遊ぶ時間がある人はここで私の最終的な作業コードです。 QLabelを拡張し、setPixmapメソッドとdrawEventメソッドをオーバーロードするという考え方です。

QPictureLabel.hpp(ヘッダーファイル)

#include "QImage.h"
#include "QPixmap.h"
#include "QLabel.h"

class QPictureLabel : public QLabel
{
private:
    QPixmap _qpSource; //preserve the original, so multiple resize events won't break the quality
    QPixmap _qpCurrent;

    void _displayImage();

public:
    QPictureLabel(QWidget *aParent) : QLabel(aParent) { }
    void setPixmap(QPixmap aPicture);
    void paintEvent(QPaintEvent *aEvent);
};

QPictureLabel.cpp(実装)

#include "QPainter.h"

#include "QPictureLabel.hpp"

void QPictureLabel::paintEvent(QPaintEvent *aEvent)
{
    QLabel::paintEvent(aEvent);
    _displayImage();
}

void QPictureLabel::setPixmap(QPixmap aPicture)
{
    _qpSource = _qpCurrent = aPicture;
    repaint();
}

void QPictureLabel::_displayImage()
{
    if (_qpSource.isNull()) //no image was set, don't draw anything
        return;

    float cw = width(), ch = height();
    float pw = _qpCurrent.width(), ph = _qpCurrent.height();

    if (pw > cw && ph > ch && pw/cw > ph/ch || //both width and high are bigger, ratio at high is bigger or
        pw > cw && ph <= ch || //only the width is bigger or
        pw < cw && ph < ch && cw/pw < ch/ph //both width and height is smaller, ratio at width is smaller
        )
        _qpCurrent = _qpSource.scaledToWidth(cw, Qt::TransformationMode::FastTransformation);
    else if (pw > cw && ph > ch && pw/cw <= ph/ch || //both width and high are bigger, ratio at width is bigger or
        ph > ch && pw <= cw || //only the height is bigger or
        pw < cw && ph < ch && cw/pw > ch/ph //both width and height is smaller, ratio at height is smaller
        )
        _qpCurrent = _qpSource.scaledToHeight(ch, Qt::TransformationMode::FastTransformation);

    int x = (cw - _qpCurrent.width())/2, y = (ch - _qpCurrent.height())/2;

    QPainter Paint(this);
    Paint.drawPixmap(x, y, _qpCurrent);
}

使用法:setScaledContentsなしで画像を表示するために通常のラベルを使用するのと同じ

img_Result = new QPictureLabel(ui.parent);
layout = new QVBoxLayout(ui.parent);
layout->setContentsMargins(11, 11, 11, 11);
ui.parent->setLayout(layout);
layout->addWidget(img_Result);

//{...}

QPixmap qpImage(qsImagePath);
img_Result->setPixmap(qpImage);
14

元のpixmapのコピーを保管してください。次に、これを実装するresized信号をスロットに接続します(またはresizeEvent()関数をオーバーライドします)。

lblImage->setPixmap(pixmap.scaled(lblImage->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
12
Tim MB