Как поправить расположение картинки в контейнере?

Я создал цветной контейнер box, в который помещаю надпись label, кнопку btn и изображение picture. К сожалению, picture я добавляю неправильно, из-за чего окно приложения выглядит так:

введите сюда описание изображения

Сейчас у меня есть три проблемы:

  1. Я масштабировал изображение так, чтобы его размер был равен размеру контейнера, но оно все равно вышло за его пределы box. Мне нужно, чтобы между боковыми стенками контейнера и изображением не было расстояния.
  2. Картинка не появляется полностью, на скрине можно видеть только ее маленькую часть. Я не понимаю, как это исправить.
  3. Мне необходимо расположить изображение в box так, чтобы оно полностью прижалось к верхней части контейнера, при этом другие виджеты контейнера должны остаться на своих местах, не изменив свой размер.

Примерно так должен выглядеть контейнер box в итоге:

введите сюда описание изображения

Пожалуйста, подскажите, как поправить расположение картинки в контейнере?

from PyQt5 import QtCore, QtWidgets, QtGui, QtMultimedia

class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent = None):
        super().__init__(parent)

        main_box = QtWidgets.QHBoxLayout(self)

        container = QtWidgets.QWidget()
        container.setStyleSheet('background: #2A303D;')
        container.setFixedWidth(250)
        container.setMinimumHeight(150)

        main_box.addWidget(container)
        box = QtWidgets.QVBoxLayout(container)

        picture = QtWidgets.QLabel()
        picture.setPixmap(QtGui.QPixmap('im.png'))
        picture.setFixedSize(250, 250)
        box.addWidget(picture)

        label = QtWidgets.QLabel('Text')
        label.setStyleSheet('color: white;')
        box.addWidget(label, alignment = QtCore.Qt.AlignCenter)

        btn = QtWidgets.QPushButton('Button')
        btn.setStyleSheet('color: white;')
        box.addWidget(btn, alignment = QtCore.Qt.AlignCenter)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle(' ')
    window.show()
    sys.exit(app.exec_())

UPD: Если использовать метод setContentsMargins(0, 0, 0, 0), то при больших размерах окна между изображением и верхней границей контейнера появляется лишнее расстояние:

введите сюда описание изображения

Пожалуйста, скажите, как от него избавиться?

from PyQt5 import QtCore, QtWidgets, QtGui, QtMultimedia

class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent = None):
        super().__init__(parent)

        main_box = QtWidgets.QHBoxLayout(self)

        container = QtWidgets.QWidget()
        container.setStyleSheet('background: #2A303D;')
        container.setFixedWidth(250)
        container.setMinimumHeight(300)

        main_box.addWidget(container)
        box = QtWidgets.QVBoxLayout(container)
        box.setContentsMargins(0, 0, 0, 0)

        picture = QtWidgets.QLabel()
        picture.setPixmap(QtGui.QPixmap('im.png').scaled(250, 250, QtCore.Qt.KeepAspectRatio))
        box.addWidget(picture)

        label = QtWidgets.QLabel('Text')
        label.setStyleSheet('color: white;')
        box.addWidget(label, alignment = QtCore.Qt.AlignCenter)

        btn = QtWidgets.QPushButton('Button')
        btn.setStyleSheet('color: white;')
        box.addWidget(btn, alignment = QtCore.Qt.AlignCenter)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle(' ')
    window.show()
    sys.exit(app.exec_())

Ответы (2 шт):

Автор решения: gil9red

Можно руками масштабировать картинку через QPixmap::scaled и если указывать Qt.KeepAspectRatio (сохранение пропорций), то должно получить как вы описали:

img = QtGui.QPixmap('im.png').scaled(250, 250, QtCore.Qt.KeepAspectRatio)
picture.setPixmap(img)

Другой вариант, если указать setScaledContents(true), тогда картинка займет все пространство QLabel:

picture.setScaledContents(True)
→ Ссылка
Автор решения: S. Nick

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

Возвращает копию растрового изображения, масштабированного до прямоугольника с заданной шириной и высотой в соответствии с заданными aspectRatioMode и transformMode. Если ширина или высота равна нулю или отрицательна, эта функция возвращает нулевое растровое изображение.

from PyQt5 import QtCore, QtWidgets, QtGui, QtMultimedia

class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent = None):
        super().__init__(parent)

        main_box = QtWidgets.QHBoxLayout(self)
        main_box.setContentsMargins(0, 0, 0, 0)                       # +++


        container = QtWidgets.QWidget()
        container.setStyleSheet('background: #2A303D;')
        container.setFixedWidth(250)
        container.setMinimumHeight(300)                               # ? 150

        main_box.addWidget(container)
        box = QtWidgets.QVBoxLayout(container)

        picture = QtWidgets.QLabel()
        picture.setPixmap(QtGui.QPixmap('im.png').scaled(250, 250))    # +++
#        picture.setFixedSize(250, 250)
        box.addWidget(picture)

        label = QtWidgets.QLabel('Text')
        label.setStyleSheet('color: white;')
        box.addWidget(label, alignment = QtCore.Qt.AlignCenter)

        btn = QtWidgets.QPushButton('Button')
        btn.setStyleSheet('color: white;')
        box.addWidget(btn, alignment = QtCore.Qt.AlignCenter)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle(' ')
    window.show()
    sys.exit(app.exec_())

введите сюда описание изображения


Update

QBoxLayout::setStretch(int index, int stretch)

Sets the stretch factor at position index. to stretch.

from PyQt5 import QtCore, QtWidgets, QtGui, QtMultimedia

class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent = None):
        super().__init__(parent)

        main_box = QtWidgets.QHBoxLayout(self)

        container = QtWidgets.QWidget()
        container.setStyleSheet('background: #2A303D;')
        container.setFixedWidth(250)
        container.setMinimumHeight(300)                               

        main_box.addWidget(container)
        box = QtWidgets.QVBoxLayout(container)
        box.setContentsMargins(0, 0, 0, 0)

        picture = QtWidgets.QLabel()
        picture.setPixmap(QtGui.QPixmap('zootopia.png').scaled(250, 250, QtCore.Qt.KeepAspectRatio))        
        box.addWidget(picture)

        label = QtWidgets.QLabel('Text')
        label.setStyleSheet('color: white;')
        box.addWidget(label, alignment = QtCore.Qt.AlignCenter)

        btn = QtWidgets.QPushButton('Button')
        btn.setStyleSheet('color: white;')
        box.addWidget(btn, alignment = QtCore.Qt.AlignCenter)

        box.setStretch(0, 0)                                         # +++
        box.setStretch(1, 1)                                         # +++
        box.setStretch(2, 1)                                         # +++

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle(' ')
    window.show()
    sys.exit(app.exec_())

введите сюда описание изображения

→ Ссылка