QPixmap维持宽高比

3
我正在编写一个程序,通过TUMBLR的API上传照片,感谢你们的帮助,我已经实现了上传功能。我在GUI的侧边栏上放置了一个“queueBox”,显示图像名称,并将它们存储在QListWidget中。我已经在我的主类构造函数中添加了这个功能。
def __init__(self):
    QtGui.QMainWindow.__init__(self)
    self.setupUi(self)
    self.queueBox.itemClicked.connect(self.displayPhoto)

我有这个方法:

def displayPhoto(self, item):
    tempName = (item.text())
    print tempName
    self.myLabel.setPixmap(QtGui.QPixmap(_fromUtf8(directory + '\\' + tempName)))  
    ## self.myLabel.pixmap(QPixmap.scaled(aspectRatioMode = Qt.IgnoreAspectRatio))
    ## ^ ^ ^ What do I do with this? How do I set it to maintain aspect ratio?
    ## Currently it says ''NameError: global name 'Qt' is not defined''

这成功地将图像绘制到我的标签(QLabel)上,但它被缩放得非常小,我需要
self.myLabel.setScaledContents(True)

在我的ui_mainWindow类中,如果我将其设置为False,则可以解决缩放问题,但它只显示图像的一小部分,因为图像比QLabel大得多。 我想要的是能够保持纵横比,这样它就不会看起来缩放和可怕。
我找到了这个:http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qpixmap.html 它说明了如何使用它,但是我无法像上面代码中的注释那样使其工作。 有人知道如何使用吗? 如果知道,请提供一个示例,我已经尝试搜索,但我得到的大多数结果都是C ++中的工作示例,而不是python。
谢谢!
2个回答

13

消除

self.myLabel.setScaledContents(True)

调用(或将其设置为False)。它会使用像素图填充您的部件,而不关心宽高比。

如果您需要调整QPixmap的大小,正如您发现的那样,scaled是所需的方法。但您正在错误地调用它。让我们来看看定义:

QPixmap QPixmap.scaled (self, 
                        int width, 
                        int height, 
                        Qt.AspectRatioMode aspectRatioMode = Qt.IgnoreAspectRatio,
                        Qt.TransformationMode transformMode = Qt.FastTransformation)

该函数的返回类型是QPixmap,因此它返回原始像素图的一个缩放副本

然后,您需要一个描述像素图(最大)最终大小的widthheight

还有两个可选参数,aspectRatioMode处理长宽比。 文档详细介绍了不同的选项及其效果。transformMode定义了缩放的方法(算法),这可能会改变最终图像的质量。您可能不需要这一个。

因此,将它们组合起来,您应该拥有以下代码(Qt命名空间在QtCore中):

# substitute the width and height to desired values
self.myLabel.setPixmap(QtGui.QPixmap(_fromUtf8(directory + '\\' + tempName)).scaled(width, height, QtCore.Qt.KeepAspectRatio))

或者,如果您有一个固定大小的QLabel,您可以调用.size()方法从中获取其大小:

self.myLabel.setPixmap(QtGui.QPixmap(_fromUtf8(directory + '\\' + tempName)).scaled(self.myLabel.size(), QtCore.Qt.KeepAspectRatio))

注意:您可能希望使用os.path.join(directory, tempName)替换directory + '\\' + tempName部分。


1
好的,非常感谢,这很有效。我稍微修改了一下: self.myLabel.setPixmap(QtGui.QPixmap(_fromUtf8(directory + '\\' + tempName)).scaled(self.myLabel.size(), QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)) 我添加了 "smoothTransformation",因为当将图像适应标签时,它可以使质量更好。然而,当图像被创建时,它位于标签的左侧,即如果它是一个正方形,它不会在标签的中间,而是在左侧,我搜索了文档,找不到任何执行我想要的操作的内容,有什么建议吗? - Anteara
哦,我上面的描述不是很清楚。我的意思是想让正方形图像位于标签中央,而不是左侧,这样它看起来与窗口的其余部分成比例。我会给你展示一个例子,你可以看到正方形图像被放在了左侧,而宽屏图像则没有问题。http://i.imgur.com/0nQWU.jpg - Anteara
@Anteara:这取决于 QLabel。只需通过 Designer(如果您是通过 Designer 设计 UI)或通过调用 self.myLabel.setAlignment(QtCore.Qt.AlignCenter) 来设置其对齐方式即可。 - Avaris
好的,如果您愿意帮忙,我又遇到了一个问题。它涉及到如何掩盖文本以便在输入密码时不会显示明文。我已经通过阅读文件文档解决了这个问题,具体做法如下: self.passWord.setEchoMode(QtGui.QLineEdit.Password) 这将使输入看起来像是密码字段中常见的样子。但出乎意料的是,这也使输出变成了通常看到的圆点,如下所示:password = smart_str(self.passWord.displayText()) print password - Anteara
请注意,我需要将其放置为smart_str而不是str,因为如果我不这样做,就会出现UnicodeEncodeError。from django.utils.encoding import smart_str, smart_unicode如果我输入一个三个字母的密码,输出将是 ●●●。输出应该显示“asd”(那是输入的内容),因为我无法验证 ●●● 以进行身份验证,这是显而易见的原因。 - Anteara
哦,没事了,我已经解决了。对于任何阅读此内容的人来说,.displayText()似乎显示掩码文本。我使用.text()来显示输入,而QLineEdit仍然显示掩码输入文本。 - Anteara

1

PyQt5代码更改更新:

avaris的上述答案需要PyQt5更新,因为它已经失效。

QPixmap.scaled (self, int width, int height, Qt.AspectRatioMode aspectRatioMode = Qt.IgnoreAspectRatio

在代码中保留 "self",会导致以下回溯错误。
TypeError: arguments did not match any overloaded call: scaled(self, int, int, aspectRatioMode: Qt.AspectRatioMode = Qt.IgnoreAspectRatio, transformMode: Qt.TransformationMode = Qt.FastTransformation): argument 1 has unexpected type 'MainUI' scaled(self, QSize, aspectRatioMode: Qt.AspectRatioMode = Qt.IgnoreAspectRatio, transformMode: Qt.TransformationMode = Qt.FastTransformation): argument 1 has unexpected type 'MainUI'
因此,应该如下所述(去掉 "self"、"Qt")。
QPixmap.scaled (int width, int height, aspectRatioMode = IgnoreAspectRatio

或者:

QPixmap.scaled (int width, int height, aspectRatioMode = 0)

KeepAspectRatio = 2...但在上述代码中使用aspectRatioMode = 2提供的方式。享受吧!


aspectRatioMode = 0aspectRatioMode = 4 是什么意思?你应该使用枚举元素名称而不是假定的值。我没有看到对应于值4的枚举元素名称 - mins
@mins 感谢您对价值的关注。我猜是笔误。 - ZF007

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接