Как поправить расположение виджетов в контейнере?
Мой код заполняет виджетами цветной контейнер box. В него попадают следующие элементы:
self.picture- некоторое изображение с закругленными краями. Я получаю его с помощью классаLabel- Три виджета
QLabel-self.label1,self.label2иself.another_label(его делаю невидимым) - Две кнопки
self.btnиself.another_btn(ее делаю невидимой)
Эти виджеты не выполняют прямых функций. Они нужны, чтобы можно было понять, как контейнер box располагает внутри себя элементы.
Контейнер box расположен в контейнере main_box. Туда же я поместил кнопку remake_btn, которая скрывает одни виджеты контейнера box и делает видимыми другие.
Первое нажатие скрывает self.picture, self.label1, self.label2, self.btn, но показывает self.another_label и self.another_btn.
Второе нажатие возвращает контейнер в прежнее состояние. Таким образом, у окна есть два состояния:
До нажатия на remake_btn:
После нажатия на remake_btn:
На втором скрине видно, что элементы self.another_label и self.another_btn притягиваются к нижней части контейнера. Думаю, что это происходит из-за того, что я использую метод addStretch(), отказаться от которого не могу. По мере наполнения box я несколько раз применяю данный метод к этому контейнеру. Нажатие на кнопку remake_btn скрывает виджеты, но не трогает пустые пространства, которые создает метод addStretch():
В зависимости от состояния окна, я бы хотел контролировать эти пустые пространства в контейнере box. Можно сказать, что мне нужно менять их количество, расположение и коэффициент их растяжения, при переходе от одного состояния окна к другому. Вот как примерно должен выглядеть контейнер box после нажатия на remake_btn:
Я думаю, можно создать второй контейнер и скрывать не виджеты, а контейнеры. Но будет ли это рациональным способом? Звучит не очень хорошо. Пожалуйста, подскажите, как мне поправить расположение виджетов в контейнере box?
from PyQt5 import QtCore, QtWidgets, QtGui, QtMultimedia
class Label(QtWidgets.QLabel):
clicked = QtCore.pyqtSignal()
def __init__(self, picture, x, *args, **kwargs):
super(Label, self).__init__(*args, **kwargs)
self.x = x
self.setMaximumSize(x, x)
self.setMinimumSize(x, x)
self.radius = 10
self.setPicture(picture)
def setPicture(self, picture):
target = QtGui.QPixmap(self.size())
target.fill(QtCore.Qt.transparent)
p = QtGui.QPixmap(picture).scaled(
self.x, self.x, QtCore.Qt.KeepAspectRatioByExpanding,
QtCore.Qt.SmoothTransformation
)
painter = QtGui.QPainter(target)
painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing, True)
painter.setRenderHint(QtGui.QPainter.SmoothPixmapTransform, True)
path = QtGui.QPainterPath()
path.addRoundedRect(0, 0, self.width(), self.height(), self.radius, self.radius)
painter.setClipPath(path)
painter.drawPixmap(0, 0, p)
self.setPixmap(target)
painter.end()
target = None
def mouseReleaseEvent(self, event):
self.clicked.emit()
class MyWindow(QtWidgets.QWidget):
def __init__(self, parent = None):
super().__init__(parent)
self.index = 1
main_box = QtWidgets.QVBoxLayout(self)
container = QtWidgets.QWidget()
container.setStyleSheet('background: #7189DB;')
container.setFixedWidth(250)
container.setMinimumHeight(282)
main_box.addWidget(container)
remake_btn = QtWidgets.QPushButton('Remake', clicked = self.remake)
main_box.addWidget(remake_btn)
box = QtWidgets.QVBoxLayout(container) # КОНТЕЙНЕР 'BOX'
self.picture = Label('picture1.png', 150)
box.addStretch(3)
box.addWidget(self.picture, alignment=QtCore.Qt.AlignCenter)
self.label1 = QtWidgets.QLabel('Text 1')
box.addStretch(2)
box.addWidget(self.label1, alignment=QtCore.Qt.AlignCenter)
self.label2 = QtWidgets.QLabel('Text 2')
box.addStretch(1)
box.addWidget(self.label2, alignment=QtCore.Qt.AlignCenter)
self.btn1 = QtWidgets.QPushButton('Button')
box.addStretch(2)
box.addWidget(self.btn1, alignment=QtCore.Qt.AlignCenter)
box.addStretch(3)
self.another_label = QtWidgets.QLabel('Another Text')
self.another_label.hide()
box.addWidget(self.another_label, alignment=QtCore.Qt.AlignCenter)
self.another_btn = QtWidgets.QPushButton('Another Button')
self.another_btn.hide()
box.addWidget(self.another_btn, alignment=QtCore.Qt.AlignCenter)
def remake(self):
if self.index == 1:
self.picture.hide()
self.label1.hide()
self.label2.hide()
self.btn1.hide()
self.another_label.show()
self.another_btn.show()
self.index = 2
else:
self.picture.show()
self.label1.show()
self.label2.show()
self.btn1.show()
self.another_label.hide()
self.another_btn.hide()
self.index = 1
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.setWindowTitle(' ')
window.show()
sys.exit(app.exec_())
Ответы (1 шт):
Я думаю, что правильно создать второй контейнер
from PyQt5 import QtCore, QtWidgets, QtGui, QtMultimedia
class Label(QtWidgets.QLabel):
clicked = QtCore.pyqtSignal()
def __init__(self, picture, x, *args, **kwargs):
super(Label, self).__init__(*args, **kwargs)
self.x = x
self.setMaximumSize(x, x)
self.setMinimumSize(x, x)
self.radius = 10
self.setPicture(picture)
def setPicture(self, picture):
target = QtGui.QPixmap(self.size())
target.fill(QtCore.Qt.transparent)
p = QtGui.QPixmap(picture).scaled(
self.x, self.x, QtCore.Qt.KeepAspectRatioByExpanding,
QtCore.Qt.SmoothTransformation
)
painter = QtGui.QPainter(target)
painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing, True)
painter.setRenderHint(QtGui.QPainter.SmoothPixmapTransform, True)
path = QtGui.QPainterPath()
path.addRoundedRect(0, 0, self.width(), self.height(), self.radius, self.radius)
painter.setClipPath(path)
painter.drawPixmap(0, 0, p)
self.setPixmap(target)
painter.end()
target = None
def mouseReleaseEvent(self, event):
self.clicked.emit()
class MyWindow(QtWidgets.QWidget):
def __init__(self, parent = None):
super().__init__(parent)
self.index = 1
main_box = QtWidgets.QVBoxLayout(self)
self.container = QtWidgets.QWidget()
self.container.setStyleSheet('background: #7189DB;')
self.container.setFixedWidth(250)
self.container.setMinimumHeight(282)
main_box.addWidget(self.container)
# remake_btn = QtWidgets.QPushButton('Remake', clicked = self.remake)
# main_box.addWidget(remake_btn)
box = QtWidgets.QVBoxLayout(self.container) # КОНТЕЙНЕР 'BOX'
self.picture = Label('im.png', 150)
box.addStretch(3)
box.addWidget(self.picture, alignment=QtCore.Qt.AlignCenter)
self.label1 = QtWidgets.QLabel('Text 1')
box.addStretch(2)
box.addWidget(self.label1, alignment=QtCore.Qt.AlignCenter)
self.label2 = QtWidgets.QLabel('Text 2')
box.addStretch(1)
box.addWidget(self.label2, alignment=QtCore.Qt.AlignCenter)
self.btn1 = QtWidgets.QPushButton('Button')
box.addStretch(2)
box.addWidget(self.btn1, alignment=QtCore.Qt.AlignCenter)
box.addStretch(3)
# ++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
self.container_2 = QtWidgets.QWidget()
self.container_2.setStyleSheet('background: #7189DB;')
self.container_2.setFixedWidth(250)
box_2 = QtWidgets.QVBoxLayout(self.container_2) # КОНТЕЙНЕР 'box_2'
box_2.addStretch(3)
self.another_label = QtWidgets.QLabel('Another Text')
box_2.addWidget(self.another_label, alignment=QtCore.Qt.AlignCenter)
box_2.addStretch(1)
self.another_btn = QtWidgets.QPushButton('Another Button')
box_2.addWidget(self.another_btn, alignment=QtCore.Qt.AlignCenter)
box_2.addStretch(3)
main_box.addWidget(self.container_2)
self.container_2.hide()
remake_btn = QtWidgets.QPushButton('Remake', clicked = self.remake)
main_box.addWidget(remake_btn)
# ++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
def remake(self):
if self.index == 1:
'''
self.picture.hide()
self.label1.hide()
self.label2.hide()
self.btn1.hide()
self.another_label.show()
self.another_btn.show()
'''
self.container.hide()
self.container_2.show()
self.index = 2
else:
'''
self.picture.show()
self.label1.show()
self.label2.show()
self.btn1.show()
self.another_label.hide()
self.another_btn.hide()
'''
self.container_2.hide()
self.container.show()
self.index = 1
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.setWindowTitle(' ')
window.show()
sys.exit(app.exec_())




