【问题标题】:Display image in Qt to fit label size在 Qt 中显示图像以适应标签大小
【发布时间】:2011-08-04 22:01:29
【问题描述】:

我已经尝试了几种在表单上显示图像的方法,但没有一种方法能达到我想要的效果。

我读过很多地方,最简单的方法是创建标签并使用它来显示图像。我有一个标签,其大小由布局指定,但是如果我使用像素图将图像加载到其中,则标签的大小将调整为图像的大小。如果我使用 img 标签作为文本或 css 背景属性,它不会显示整个图像。我想做的是加载图像并适合标签,而不是改变标签的大小,但是当我调整我的窗口大小时,通过调整标签的大小,图像也应该调整大小,所以它总是适合进入它。

如果唯一的方法是获取标签的大小,并调整像素图的大小以使其适合,并处理调整大小事件(信号),我该如何调整像素图的大小?我希望我不需要每次都将整个内容保存到 QImage 并从中创建一个像素图。

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

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

【问题讨论】:

    标签: image qt autoresize


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 我想没有简单的解决方案来保持图像的宽高比?
    • “忽略”的问题是标签不能用于“扩展”布局。
    • 使用 PyQt5,这也行不通。 QSizePolicy.Ignored 似乎不会影响图像是否调整大小。
    【解决方案2】:

    QLabel::setScaledContents(bool) 有帮助吗? image viewer example也可能有一些有用的信息。

    【讨论】:

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

    保留一份原始pixmap 的副本。然后将resized 信号连接到实现此功能的插槽(或覆盖resizeEvent() 函数):

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

    【讨论】:

    • pixmap.scaled - 创建一个缩放的副本,因此将使用额外的内存。
    • 是的,您需要您的缩放版本作为副本。如果您只是调整同一图像的大小,那么先缩小再放大会导致质量下降。
    【解决方案4】:

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

    【讨论】:

    • 很好的回复,我只有我的父小部件有问题,它有问题
    • 当我改变像素图和调整屏幕大小时它会出错
    • 这是很久以前的事了(1 年对我来说太多了),我什至没有安装 Qt,但我也许可以提供帮助。你得到什么错误,在哪一行?你试过调试吗?或者它是如何“出错”的?您可以在这里做的最好的事情是在 stackoverflow 上发布后续问题,这样您就有更大的机会从整个用户群中获得答案。
    • 很抱歉,当我的主窗口调整大小时,我的标签也调整了大小,所以标签的背景有问题,而不是标签本身的图像 - 你的代码 - 我修复了让我的标签带有背景标签->setAutoFillBackground(true);
    • 非常感谢这个 QLabel 扩展!节省了我的工作时间。
    【解决方案5】:

    ui-&gt;label-&gt;setPixmap( pix.scaled( ui-&gt;label-&gt;size(), Qt::KeepAspectRatio, Qt::SmoothTransformation) );

    对我的案例(Qt 5.11)很有魅力。 pix 是具有原始像素数的 QPixmap 对象(例如,使用 QPixmap::fromImage(path) 构造)。

    【讨论】:

      【解决方案6】:

      在 Qt Designer 中,你必须设置两件事:

      1. 将像素图设置为您想要的图像
      2. 检查 scaledContents

      如下图:

      这里,底部的标签被scaledContents选中,顶部的标签没有被选中。

      【讨论】:

        【解决方案7】:
        QPixmap pic = QPixmap(":/resource/xxx.png").scaled(16,16,Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
        
        ui->yourLable->setPixmap(pic);
        

        【讨论】:

        • 与@Team MB 的答案相同,除了 Qt::IgnoreAspectRatio 我认为与问题不匹配
        • 其实我找到了另一个更好的解决方案,就是ui-&gt;yourLabel-&gt;setPixmap(QIcon("xx.png").pixmap(16,16));
        【解决方案8】:

        对于 python 用户,解决方案的工作方式如下:

        先保留原来的“setQPixmap”行

        self.thumbnail.setPixmap(QPixmap(image))
        

        然后添加以下行:

        self.thumbnail.setScaledContents(1)
        

        “1”将“setScaledContents”设置为 true,这会始终缩放图像以适合 Qlabel 的当前大小。

        【讨论】:

          猜你喜欢
          • 2016-02-26
          • 1970-01-01
          • 2013-06-25
          • 1970-01-01
          • 2020-08-26
          • 2023-04-01
          • 2013-11-23
          • 2015-07-02
          • 1970-01-01
          相关资源
          最近更新 更多