сохранить виджет макета сетки как квадрат

Это должно быть легко, но я все больше и больше сбиваюсь с толку, глядя на предлагаемые ответы, которые не работают. Все, что я хочу сделать, это иметь возможность иметь кучу виджетов в макете сетки, где изменение размера окна приведет к изменению размера виджетов внутри сетки, чтобы заполнить пространство, где это возможно, но сохранить их соотношение сторон (квадрат в данном случае как это сетка из квадратов 2x2).

Вот код без каких-либо моих неудачных попыток сделать это. Изначально я планировал ограничить само окно фиксированным соотношением сторон, но не смог заставить это работать. Я соглашусь на фрейм (или другой виджет / макет), имеющий эту функцию. Предельный размер квадрата не важен, пока он растягивается и сжимается вместе с окном, сохраняя при этом квадратное содержимое. Здесь я использую PySide6, но решение с PyQt5 подойдет. C++, хотя и не очень, я в нем грамотный. Требуется ли индивидуальная обработка изменения размера? Кажется, я не могу заставить работать heightForWidth.

      import sys
from PySide6.QtWidgets import QApplication, QDialog, QWidget, QFrame, QGridLayout


class MyDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.resize(600, 600)
        self.my_frame = QFrame(self)
        self.my_frame.setObjectName(u"my_frame")
        self.my_frame.setGeometry(50, 50, 250, 250)
        self.my_frame.setBaseSize(100, 100)
        self.gridLayout = QGridLayout(self.my_frame)
        self.gridLayout.setSpacing(0)
        self.gridLayout.setObjectName("gridLayout")

        self.top_left = QWidget(self.my_frame)
        self.top_left.setObjectName("top_left")
        self.top_left.setStyleSheet("background-color: rgb(235, 10, 30)")
        self.gridLayout.addWidget(self.top_left, 0, 0, 1, 1)

        self.top_right = QWidget(self.my_frame)
        self.top_right.setObjectName("top_right")
        self.top_right.setStyleSheet("background-color: rgb(55, 122, 70)")
        self.gridLayout.addWidget(self.top_right, 0, 1, 1, 1)

        self.bottom_left = QWidget(self.my_frame)
        self.bottom_left.setObjectName("bottom_left")
        self.bottom_left.setStyleSheet("background-color: rgb(55, 122, 190)")
        self.gridLayout.addWidget(self.bottom_left, 1, 0, 1, 1)

        self.bottom_right = QWidget(self.my_frame)
        self.bottom_right.setObjectName("bottom_right")
        self.bottom_right.setStyleSheet("background-color: rgb(235, 219, 70)")
        self.gridLayout.addWidget(self.bottom_right, 1, 1, 1, 1)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    dialog = MyDialog()
    dialog.show()
    exit(app.exec_())

1 ответ

Решение

QLayout (например, QGridLayout) - это обработчики размера, а не визуальные элементы, поэтому нет смысла говорить, что они квадратные. С другой стороны, QGridLayout устанавливает геометрию виджетов, основываясь в основном на размере контейнера.

Таким образом, в этом случае вы должны сделать его квадратным в зависимости от размера окна, поэтому для этого вы должны переопределить метод resizeEvent и вычислить размер максимального квадрата, вписанного в окно. и, возможно, вам также следует центрировать контейнер.

      class MyDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.resize(600, 600)
        qss = """
            #top_left{
                background-color: rgb(235, 10, 30)
            }
            #top_right{
                background-color: rgb(55, 122, 70)
            }
            #bottom_left{
                background-color: rgb(55, 122, 190)
            }
            #bottom_right{
                background-color: rgb(235, 219, 70)
            }
        """
        self.setStyleSheet(qss)

        self.my_frame = QFrame(self, objectName="my_frame")
        self.gridLayout = QGridLayout(self.my_frame, objectName="gridLayout")
        self.gridLayout.setSpacing(0)

        self.top_left = QWidget(objectName="top_left")
        self.gridLayout.addWidget(self.top_left, 0, 0, 1, 1)

        self.top_right = QWidget(objectName="top_right")
        self.gridLayout.addWidget(self.top_right, 0, 1, 1, 1)

        self.bottom_left = QWidget(objectName="bottom_left")
        self.gridLayout.addWidget(self.bottom_left, 1, 0, 1, 1)

        self.bottom_right = QWidget(objectName="bottom_right")
        self.gridLayout.addWidget(self.bottom_right, 1, 1, 1, 1)

    def resizeEvent(self, event):
        super().resizeEvent(event)

        l = min(self.width(), self.height())
        center = self.rect().center()

        rect = QRect(0, 0, l, l)
        rect.moveCenter(center)
        self.my_frame.setGeometry(rect)
Другие вопросы по тегам