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

问题描述 投票:0回答:9

我已经尝试了几种在表单上显示图像的方法,但没有一个能按照我想要的方式工作。

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

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

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

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

image qt autoresize
9个回答
35
投票

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

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

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

如果

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


28
投票

QLabel::setScaledContents(bool) 有帮助吗? 图像查看器示例中也可能有一些有用的信息。


25
投票
保留一份原件

pixmap

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

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

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

3
投票
在 Qt Designer 中,您必须设置两件事:

    将像素图设置为您想要的图像
  1. 检查
  2. 缩放内容
如下图:

此处,底部的标签已选中

scaledContents,而顶部的标签未选中。


2
投票

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



对我的案例来说非常有效(Qt 5.11)。

pix

 是具有原始像素数的 
QPixmap
 对象(例如用 
QPixmap::fromImage(path)
 构造)。


1
投票
QPixmap pic = QPixmap(":/resource/xxx.png").scaled(16,16,Qt::IgnoreAspectRatio, Qt::SmoothTransformation); ui->yourLable->setPixmap(pic);
    

1
投票
Python 解决方案

# Created by [email protected] at 2022/2/4 11:28 import urllib.request from PySide2 import QtWidgets, QtGui, QtCore class PictureLabel(QtWidgets.QLabel): def __init__(self, text: str = None, pixmap: QtGui.QPixmap = None): super().__init__() self._pixmap = None text is not None and self.setText(text) pixmap is not None and self.setPixmap(pixmap) def setPixmap(self, pixmap: QtGui.QPixmap) -> None: self._pixmap = pixmap self.repaint() def paintEvent(self, event: QtGui.QPaintEvent) -> None: super().paintEvent(event) if self._pixmap is not None: imageWidth, imageHeight = self._pixmap.width(), self._pixmap.height() labelWidth, labelHeight = self.width(), self.height() ratio = min(labelWidth / imageWidth, labelHeight / imageHeight) newWidth, newHeight = int(imageWidth * ratio), int(imageHeight * ratio) newPixmap = self._pixmap.scaledToWidth(newWidth, QtCore.Qt.TransformationMode.FastTransformation) x, y = abs(newWidth - labelWidth) // 2, abs(newHeight - labelHeight) // 2 QtGui.QPainter(self).drawPixmap(x, y, newPixmap) app = QtWidgets.QApplication() pixmap = QtGui.QPixmap() pixmap.loadFromData(urllib.request.urlopen("https://www.baidu.com/favicon.ico").read()) label = PictureLabel(pixmap=pixmap) label.resize(800, 600) label.show() app.exec_()
    

0
投票
对于 python 用户,解决方案将像这样工作:

首先保留原来的“setQPixmap”行

self.thumbnail.setPixmap(QPixmap(image))
然后添加以下行:

self.thumbnail.setScaledContents(1)
“1”将“setScaledContents”设置为 true,从而始终缩放图像以适合 Qlabel 的当前大小。

© www.soinside.com 2019 - 2024. All rights reserved.