我已经尝试了几种在表单上显示图像的方法,但没有一个能按照我想要的方式工作。
我读过很多地方,最简单的方法是创建标签并使用它来显示图像。我有一个标签,其大小由布局指定,但是如果我使用像素图将图像加载到其中,标签的大小将调整为图像的大小。如果我使用 img 标签作为文本或 css 背景属性,它不会显示整个图像。我想做的是加载图像并适合标签,而不是更改标签的大小,但是当我调整窗口大小并调整标签大小时,图像也应该调整大小,以便它始终适合进入其中。
如果唯一的方法是获取标签的大小,然后调整像素图的大小以使其适合,并处理调整大小事件(信号),那么我如何调整像素图的大小?我希望我不需要将整个内容保存到 QImage 中并每次都从中创建一个像素图。
另外,如何将其居中?如果它不能同时适合宽度和高度,我希望较小的尺寸居中。
哦,我不想使用滑块来处理溢出。
其实这个问题有一个非常简单的解决方案。您应该修改两件事:
将标签的尺寸策略设置为忽略
QLabel lblImage;
lblImage->setPixmap( QPixmap( "big_image.jpg" ) );
lblImage->setScaledContents( true );
lblImage->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored );
如果
lblImage
自动调整大小,图像将拉伸到标签的大小。
QLabel::setScaledContents(bool) 有帮助吗? 图像查看器示例中也可能有一些有用的信息。
pixmap
的副本。然后将
resized
信号连接到实现此功能的插槽(或覆盖
resizeEvent()
函数):
lblImage->setPixmap(pixmap.scaled(lblImage->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
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);
ui->label->setPixmap( pix.scaled( ui->label->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation) );
pix
是具有原始像素数的
QPixmap
对象(例如用
QPixmap::fromImage(path)
构造)。
QPixmap pic = QPixmap(":/resource/xxx.png").scaled(16,16,Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
ui->yourLable->setPixmap(pic);
# 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_()
首先保留原来的“setQPixmap”行
self.thumbnail.setPixmap(QPixmap(image))
然后添加以下行:
self.thumbnail.setScaledContents(1)
“1”将“setScaledContents”设置为 true,从而始终缩放图像以适合 Qlabel 的当前大小。