Mostrar la imagen en Qt para ajustarse al tamaño de la etiqueta


Ya probé varios métodos para mostrar una imagen en un formulario, pero ninguno de ellos funciona como me gustaría.

Yo he leído en muchos lugares que la forma más fácil es crear una etiqueta para mostrar la imagen. Tengo una etiqueta, cuyo tamaño está especificado por el diseño, pero si cargo una imagen con un mapa de píxeles, la etiqueta se redimensiona al tamaño de la imagen. Si uso la etiqueta img como propiedad de fondo de texto o css, no mostrará toda la imagen. Lo que me gustaría hacer es cargar la imagen y encajar en la etiqueta, no cambiar el tamaño de la etiqueta, pero cuando cambio el tamaño de mi ventana, y por eso cambiar el tamaño de la etiqueta, así, la imagen debe ser redimensionada también por lo que siempre encajará en ella.

Si el único método es obtener el tamaño de la etiqueta, y cambiar el tamaño del mapa de píxeles para que quepa, y manejar el evento de cambio de tamaño (señal), ¿cómo podría cambiar el tamaño del mapa de píxeles? Espero no tener que guardar todo en un QImage y crear un pixmap a partir de él cada vez.

Además, ¿cómo puedo centrarlo? Si no puede ajustarse tanto a la anchura como a la altura, me gustaría que la dimensión más pequeña estuviera centrada.

Ah, y no quiero usar controles deslizantes para manejar desbordamientos.

Author: Tetsujin no Oni, 2011-04-13

4 answers

¿Ayuda QLabel::setScaledContents(bool)? También puede haber información útil en el ejemplo del visor de imágenes .

 18
Author: Arnold Spence,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-05 10:05:19

En realidad hay una resolución muy simple para este problema. Hay dos cosas que debes modificar:

  1. establezca el contenido escalado en true (mencionado anteriormente)
  2. Establecer la política de tamaño de la etiqueta en ignorado

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

Si el lblImage se redimensiona automáticamente, la imagen se estirará al tamaño de la etiqueta.

 17
Author: bukkfa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-19 09:07:05

También responderé a mi propia pregunta, pero no la marcaré como solución, porque pedí una simple que se dio arriba. Terminé usando una solución no demasiado simple después de todo, por lo que cualquier persona que también necesita hacer algo similar y tiene el tiempo para jugar con él aquí está mi código de trabajo final. La idea es expandir el QLabel y sobrecargar los métodos setPixmap y drawEvent.

QPictureLabel.hpp (archivo de cabecera)

#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 (aplicación)

#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);
}

Usage : lo mismo que usar una etiqueta normal para mostrar la imagen fuera de 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);
 13
Author: Máthé Endre-Botond,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-23 11:13:52

Mantenga una copia de su original pixmap alrededor. Luego conecte la señal resized a una ranura (o anule la función resizeEvent()) que implementa esto :

lblImage->setPixmap(pixmap.scaled(lblImage->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
 6
Author: Tim MB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-23 16:36:42