在调整大小时保持 QLabel 中图像的纵横比 window

Keep aspect ratio of image in a QLabel whilst resizing window

假设我有这样的布局:

我希望左边物体和右边物体的比例永远是这样的:

这样我就可以在左上角添加一个小图像,它既不会太大也不会太小,但总是与 window 的大小保持良好的关系。我如何在设计器或代码中执行此操作?

我已经发现您 似乎 能够通过选择布局并将 LayoutStretch 更改为 1,3 之类的东西来做到这一点 - 这有效然而,在设计器中,当我在代码中插入我的图像时,它不尊重它并再次将布局吹出比例。

我添加了一个拉伸器并使用 QLabel 来显示图像,然后通过 self.LogoLabel.setPixmap(QtGui.QPixmap('res/image.png')) 添加了文件,所以我不明白我需要更改什么才能使图像始终保持美观和左上角的小号。

一个测试示例,以防问题不够清楚 - 我需要的图像是 1000x710px 大。

from PyQt5 import QtCore, QtWidgets, QtGui
import sys

class Ui_ZEBRA(object):

    def setupUi(self, ZEBRA):
        ZEBRA.setObjectName("ZEBRA")
        ZEBRA.resize(315, 134)
        self.centralwidget = QtWidgets.QWidget(ZEBRA)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout_4.setObjectName("verticalLayout_4")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setContentsMargins(-1, -1, -1, 0)
        self.horizontalLayout.setSpacing(0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.verticalLayout_3 = QtWidgets.QVBoxLayout()
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.LogoLabel = QtWidgets.QLabel(self.centralwidget)
        self.LogoLabel.setText("")
        self.LogoLabel.setScaledContents(True)
        self.LogoLabel.setObjectName("LogoLabel")
        self.verticalLayout_3.addWidget(self.LogoLabel)
        spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout_3.addItem(spacerItem)
        self.ComboBox_InputType = QtWidgets.QComboBox(self.centralwidget)
        self.ComboBox_InputType.setObjectName("ComboBox_InputType")
        self.ComboBox_InputType.addItem("")
        self.ComboBox_InputType.addItem("")
        self.ComboBox_InputType.addItem("")
        self.ComboBox_InputType.addItem("")
        self.verticalLayout_3.addWidget(self.ComboBox_InputType)
        self.horizontalLayout.addLayout(self.verticalLayout_3)
        self.TextInput_Devices = QtWidgets.QPlainTextEdit(self.centralwidget)
        self.TextInput_Devices.setObjectName("TextInput_Devices")
        self.horizontalLayout.addWidget(self.TextInput_Devices)
        self.horizontalLayout.setStretch(0, 1)
        self.horizontalLayout.setStretch(1, 3)
        self.verticalLayout_4.addLayout(self.horizontalLayout)
        ZEBRA.setCentralWidget(self.centralwidget)
        self.menuBar_EnterToken = QtWidgets.QAction(ZEBRA)
        self.menuBar_EnterToken.setObjectName("menuBar_EnterToken")
        self.menuBar_TestToken = QtWidgets.QAction(ZEBRA)
        self.menuBar_TestToken.setObjectName("menuBar_TestToken")
        self.menuBar_About = QtWidgets.QAction(ZEBRA)
        self.menuBar_About.setObjectName("menuBar_About")

        self.retranslateUi(ZEBRA)
        QtCore.QMetaObject.connectSlotsByName(ZEBRA)

    def retranslateUi(self, ZEBRA):
        _translate = QtCore.QCoreApplication.translate
        ZEBRA.setWindowTitle(_translate("ZEBRA", "ZEBRA"))
        self.ComboBox_InputType.setItemText(0, _translate("ZEBRA", "ip"))
        self.ComboBox_InputType.setItemText(1, _translate("ZEBRA", "Use all devices"))
        self.ComboBox_InputType.setItemText(2, _translate("ZEBRA", "displayName"))
        self.ComboBox_InputType.setItemText(3, _translate("ZEBRA", "id"))
        self.menuBar_EnterToken.setText(_translate("ZEBRA", "Enter Accesstoken"))
        self.menuBar_TestToken.setText(_translate("ZEBRA", "Test Accesstoken"))
        self.menuBar_About.setText(_translate("ZEBRA", "About..."))


class Test(QtWidgets.QMainWindow, Ui_ZEBRA):
    def __init__(self, parent=None):
        super(Test, self).__init__(parent)
        self.setupUi(self)
        self.LogoLabel.setPixmap(QtGui.QPixmap('res/image.png'))

def main():
    app = QtWidgets.QApplication(sys.argv)
    form = Test()
    form.show()
    app.exec_()



if __name__ == '__main__':
    main()

编辑:奇怪的是,我找不到关于如何在 QLabel 中使用图像并在更改 window 大小的同时缩放其大小,同时保持纵横比的单个工作示例。这么基础的东西哪里找得到?

您首先需要更改布局,使其使用对齐方式而不是扩展间隔符来使标签保持在左上角。此外,标签的某些属性需要调整,以便它可以自由调整自己的大小。这一切都可以在 Qt Designer 中完成,但您的示例代码也可以像这样手动修复:

self.LogoLabel = QtWidgets.QLabel(self.centralwidget)
self.LogoLabel.setText("")
self.LogoLabel.setObjectName("LogoLabel")

# new stuff
self.LogoLabel.setScaledContents(False)
self.LogoLabel.setMinimumSize(1, 1)
self.LogoLabel.setSizePolicy(
    QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
self.LogoLabel.setAlignment(QtCore.Qt.AlignTop)
self.verticalLayout_3.setAlignment(QtCore.Qt.AlignTop)

self.verticalLayout_3.addWidget(self.LogoLabel)

然后可以使用事件过滤器处理动态调整大小,如下所示:

class Test(QtWidgets.QMainWindow, Ui_ZEBRA):
    def __init__(self, parent=None):
        super(Test, self).__init__(parent)
        self.setupUi(self)
        self._logo = QtGui.QPixmap('res/image.png')
        self.LogoLabel.setPixmap(self._logo)
        self.LogoLabel.installEventFilter(self)

    def eventFilter(self, widget, event):
        if event.type() == QtCore.QEvent.Resize and widget is self.LogoLabel:
            self.LogoLabel.setPixmap(self._logo.scaled(
                self.LogoLabel.width(), self.LogoLabel.height(),
                QtCore.Qt.KeepAspectRatio))
            return True
        return super(Test, self).eventFilter(widget, event)

要根据需要缩小图像并保持两个元素之间的比例,您需要这样设置 setScaledContents(True)

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(559, 289)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.label = QtWidgets.QLabel(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
        self.label.setSizePolicy(sizePolicy)
        self.label.setScaledContents(True)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.label.setObjectName("label")
        self.verticalLayout.addWidget(self.label)
        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox.setObjectName("comboBox")
        self.verticalLayout.addWidget(self.comboBox)
        self.horizontalLayout.addLayout(self.verticalLayout)
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
        self.textBrowser.setObjectName("textBrowser")
        self.horizontalLayout.addWidget(self.textBrowser)
        self.horizontalLayout.setStretch(0, 1)
        self.horizontalLayout.setStretch(2, 3)
        self.verticalLayout_2.addLayout(self.horizontalLayout)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label.setText(_translate("MainWindow", "TextLabel"))

import sys
class Test(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Test, self).__init__(parent)
        self.setupUi(self)
        pixmap = QtGui.QPixmap('res/image.png')
        pixmap = pixmap.scaled(256, 128, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
        self.label.setPixmap(pixmap)
        self.label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)


def main():
    app = QtWidgets.QApplication(sys.argv)
    form = Test()
    form.show()
    app.exec_()



if __name__ == '__main__':
    main()

为了保持纵横比 - 我认为您必须使用包含标签的 Widget 的 resizeEvent,它会在触发事件时将大小更改为正确的纵横比。