Отобразить изображение в Qt, чтобы соответствовать размеру метки - PullRequest
26 голосов
/ 13 апреля 2011

Я уже пробовал несколько способов отображения изображения в форме, но ни один из них не работает так, как мне бы хотелось.

Я читал много мест, где проще всего создать ярлык и использовать его для отображения изображения.У меня есть метка, размер которой определяется макетом, но если я загружаю в нее изображение с растровым изображением, размер метки изменяется в соответствии с размером изображения.Если я использую тег img в качестве свойства фона text или css, он не будет отображать все изображение.То, что я хотел бы сделать, это загрузить изображение и вписаться в ярлык, не изменяя размер ярлыка, но когда я изменяю размер своего окна, и, соответственно, изменяя размер ярлыка, размер изображения также должен быть изменен, чтобы он всегда соответствовалв него.

Если единственный метод состоит в том, чтобы получить размер метки и изменить размер растрового изображения таким образом, чтобы он соответствовал, и обработать событие (сигнал) изменения размера, как я могу изменить размер растрового изображения?Надеюсь, мне не нужно будет сохранять все это в QImage и каждый раз создавать из него растровое изображение.

Кроме того, как я могу отцентрировать его?Если он не может соответствовать ширине и высоте, я бы хотел, чтобы меньший размер был центрирован.

О, и я не хочу использовать ползунки для обработки переполнений.

Ответы [ 4 ]

18 голосов
/ 08 августа 2014

На самом деле существует очень простое решение этой проблемы. Вы должны изменить две вещи:

  1. установить для масштабированного содержимого значение true (упомянуто выше)
  2. установить политику размера этикетки на игнорируемую

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

Если размер lblImage изменяется автоматически, изображение будет растягиваться до размера метки.

18 голосов
/ 13 апреля 2011

Помогает ли QLabel :: setScaledContents (bool) ? Также может быть некоторая полезная информация в примере просмотра изображений .

14 голосов
/ 23 апреля 2011

Я также отвечу на свой вопрос, но не буду отмечать его как решение, потому что я попросил простой вопрос, который был дан выше. В конце концов, я использовал не слишком простое решение, поэтому каждый, кому нужно сделать что-то похожее и у него есть время поиграть, вот мой последний рабочий код. Идея состоит в том, чтобы расширить 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);
12 голосов
/ 23 апреля 2016

Держите копию вашего оригинала pixmap рядом. Затем подключите сигнал resized к слоту (или переопределите функцию resizeEvent()), который реализует это:

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