【问题标题】:QPixmap maintain aspect ratioQPixmap保持纵横比
【发布时间】:2021-05-29 16:20:51
【问题描述】:

我正在编写一个程序,允许我通过他们的 API 将照片上传到 TUMBLR,我已经完成了上传工作(感谢你们)。

我在 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''

这成功地将图像绘制到 myLabel 上,这是一个 QLabel,但是,它非常缩放,我有

self.myLabel.setScaledContents(True)

在我的 ui_mainWindow 类中,如果我将其设置为 False,它会修复缩放,但它只显示图像的一小部分,因为图像比 QLabel 大得多。我想要的是能够保持纵横比,所以它看起来不会缩放和可怕。

我发现了这个:http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qpixmap.html 它说明了如何使用它,但是我无法让它像上面我的 cmets 中的代码所示那样工作。有谁知道如何使用这个?如果是这样,您能否提供一个示例,我已经尝试过搜索,但我得到的大多数结果都是 C++ 中的工作示例,而不是 python。

谢谢!

【问题讨论】:

    标签: python pyqt4 aspect-ratio qpixmap qlabel


    【解决方案1】:

    摆脱

    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,因此它返回原始像素图的缩放副本

    然后你需要一个width 和一个height,描述像素图的(最大)最终大小。

    另外两个可选参数。 aspectRatioMode 处理井纵横比。 documentation 详细说明了不同的选项及其效果。 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 部分。

    【讨论】:

    • 好的,非常感谢,效果很好。我对其进行了一些修改:self.myLabel.setPixmap(QtGui.QPixmap(_fromUtf8(directory + '\\' + tempName)).scaled(self.myLabel.size(), QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)) 我添加了“smoothTransformation”,因为它使图像适合标签时质量更好。但是,创建图像时,它位于标签的左侧,即如果它是正方形,则不会在标签的中间,而是在左侧,我搜索了文档并找不到有什么可以执行我所追求的,有什么想法吗?
    • 哦,我在上面提供的信息不是很多。我想要做的是在标签中间有一个方形图像,而不是左边,所以它看起来与窗口的其余部分成比例。我将向您展示我的意思的示例:i.imgur.com/0nQWU.jpg 如您所见,方形图像位于左侧而不是中间,但宽屏图像很好。
    • @Anteara:这取决于QLabel。只需通过 Designer(如果您通过 Designer 设计 UI)或调用 self.myLabel.setAlignment(QtCore.Qt.AlignCenter) 为其设置对齐方式。
    • 好吧,如果你愿意帮忙,我又遇到了一个问题;也就是说,屏蔽文本,以便在您输入密码时不会显示。通过阅读文档,我已经能够做到这一点:self.passWord.setEchoMode(QtGui.QLineEdit.Password) 这使输入成为您通常在密码字段中看到的内容,但是,令我惊讶的是,这也使输出成为常见的圆圈,如图所示通过这个:password = smart_str(self.passWord.displayText()) print password
    • 请注意,我需要将其设置为 smart_str 而不是 str,因为如果我不这样做,我会收到 UnicodeEncodeError。 from django.utils.encoding import smart_str, smart_unicode 如果我输入 3 个字母的密码,这就是输出 ●●●。输出应为“asd”(即输入),因为出于显而易见的原因,我无法验证●●● 进行身份验证。
    【解决方案2】:

    PyQt5代码变更更新:

    avaris 的上述答案需要 PyQt5 更新,因为它会中断。

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

    在代码中保留self 会导致以下回溯错误。

    TypeError:参数不匹配任何重载调用:缩放(self,int,int,aspectRatioMode:Qt.AspectRatioMode = Qt.IgnoreAspectRatio,transformMode:Qt.TransformationMode = Qt.FastTransformation):参数1具有意外类型'MainUI' scaled(self, QSize, aspectRatioMode: Qt.AspectRatioMode = Qt.IgnoreAspectRatio, transformMode: Qt.TransformationMode = Qt.FastTransformation): 参数 1 的类型为 '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?,您应该使用枚举元素名称而不是假定值。 I don't see one corresponding to value 4.
    • @mins 感谢您对价值的关注。我猜是错字。