在Qt中显示图像以适合标签尺寸

Mát*_*ond 28 qt image autoresize

我已经尝试了几种在表单上显示图像的方法,但它们都没有按照我的意愿运行.

我读过许多地方,最简单的方法是创建标签并使用它来显示图像.我有一个标签,其大小由布局指定,但如果我用像素图加载图像,标签将调整大小为图像的大小.如果我使用img标签作为text或css background属性,它将不会显示整个图像.我想要做的是加载图像并适合标签,而不是更改标签的大小,但是当我调整窗口大小时,以及调整标签大小时,图像也应调整大小以使其始终适合进去.

如果唯一的方法是获取标签的大小,并调整像素图以适应它,并处理调整大小事件(信号),我怎么能调整像素图的大小?我希望我不需要将整个事物保存到QImage中并且每次都从它创建一个像素图.

另外,我该如何居中呢?如果它不能同时适合宽度和高度,我希望较小的尺寸居中.

哦,我不想使用滑块来处理溢出.

Arn*_*nce 21

是否QLabel :: setScaledContents(布尔)帮助?图像查看器示例中也可能存在一些有用的信息.

  • 对于快速解决方案,这是一个节省器,但它通过拉伸图像(即:不保持纵横比)给了我一个非常难看的结果.无论如何,我会将此标记为解决方案.谢谢. (2认同)
  • 使用PyQt5,此解决方案不起作用。setScaledContents似乎对显示的图像大小没有任何影响。 (2认同)
  • `ui->label->setPixmap( pix.scaled( ui->label->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation) );` 对我来说很有魅力。`pix` 是一个具有原始像素计数的 `QPixmap` 对象(例如用 `QPixmap::fromImage(path)` 构造)。 (2认同)

小智 20

实际上这个问题有一个非常简单的解决方案.您应该修改两件事:

  1. 将缩放内容设置为true(如上所述)
  2. 将标签的大小策略设置为忽略

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

如果lblImage自动调整大小,图像将拉伸到标签的大小.


Tim*_* MB 16

保留原件的副本pixmap.然后将resized信号连接到resizeEvent()实现此的插槽(或覆盖函数):

lblImage->setPixmap(pixmap.scaled(lblImage->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
Run Code Online (Sandbox Code Playgroud)

  • 是的,您需要将缩放版本作为副本。如果您只是调整同一图像的大小,那么先缩小再放大会导致质量下降。 (2认同)

Mát*_*ond 14

我也会回答我自己的问题,但不会将其标记为解决方案,因为我要求上面给出一个简单的问题.毕竟我最终使用了一个不太简单的解决方案,所以任何需要做类似事情并且有时间在这里玩的人都是我的最终工作代码.我们的想法是扩展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);
};
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

用法:与使用普通标签显示图像wirthout 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);
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢您对此QLabel扩展!节省了我几个小时的工作. (2认同)