Размер приложения не изменяется при вызове size () после скрытия виджетов - PullRequest
2 голосов
/ 16 мая 2019

Я пытаюсь изменить размер моего приложения до меньшего размера после того, как виджет скрыт, а его sizePolicy установлен на Ignored.Однако приложение не изменится до меньшего размера, чем было раньше, как если бы скрытый виджет все еще находился там, занимая место.

Я пробовал включить self.update(), self.updateGeometry() и app.processEvents() послескрытие второго виджета / установка его sizePolicy на Ignored и перед попыткой изменить размер приложения, но ни один из них, похоже, не имеет никакого эффекта.

class App(QWidget):
    def __init__(self):
        super().__init__()

        # basic setup
        self.move(100, 100)

        # main widgets
        self.advanced_metadata = QCheckBox("Advanced", self)
        self.advanced_metadata.stateChanged.connect(self.displayAdvanced)
        self.first_widget = QLabel('first_widget', self)
        self.second_widget = QLabel('second_widget', self)
        self.second_widget.setHidden(True)
        self.second_widget.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)

        # main layout
        self.setLayout(QVBoxLayout())
        self.layout().addWidget(self.advanced_metadata)
        self.layout().addWidget(self.first_widget)
        self.layout().addWidget(self.second_widget)
        self.layout().addStretch()

        self.resizeApp(650, self.sizeHint().height())

        self.show()

    # toggles advanced metadata view
    def displayAdvanced(self):
        if self.advanced_metadata.isChecked():
            self.second_widget.setVisible(True)
            self.second_widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)

            self.resizeApp(650, self.sizeHint().height())

        else:
            self.second_widget.setHidden(True)
            self.second_widget.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)

            self.resizeApp(650, self.sizeHint().height())

    # resizes main window
    def resizeApp(self, width, height):
        self.resize(width, height)
        print(self.size())

if __name__ == '__main__':
    # accounts for exiting errors in python
    if not QApplication.instance():
        app = QApplication(sys.argv)
    else:
        app = QApplication.instance()
    ex = App()
    app.exec_()

Я ожидаю, что размер окна при инициализации будет 650x112,затем, когда установлен флажок Advanced, размер должен измениться на 650x149, и, наконец, когда флажок Advanced снят, размер должен вернуться к 650x112.Последнее ожидание не происходит;вместо этого окно остается в 650x149.

1 Ответ

1 голос
/ 16 мая 2019

В Qt многие задачи выполняются асинхронно, и это имеет место в случае геометрии, поэтому даже если вы изменили политики, это не будет применено немедленно, пока синхронная часть не закончится. Таким образом, обходной путь должен использовать QTimer.singleShot(0, ...) для применения изменения размера через мгновение.

from functools import partial
from PyQt5 import QtCore, QtWidgets


class App(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.move(100, 100)
        # main widgets
        self.advanced_metadata = QtWidgets.QCheckBox(
            "Advanced", stateChanged=self.displayAdvanced
        )
        self.first_widget = QtWidgets.QLabel("first_widget")
        self.second_widget = QtWidgets.QLabel("second_widget")
        self.second_widget.setHidden(True)
        self.second_widget.setSizePolicy(
            QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored
        )
        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.advanced_metadata)
        lay.addWidget(self.first_widget)
        lay.addWidget(self.second_widget)
        lay.addStretch()

        self.resizeApp(650, self.sizeHint().height())

    # toggles advanced metadata view
    @QtCore.pyqtSlot(int)
    def displayAdvanced(self, state):
        if state == QtCore.Qt.Checked:
            self.second_widget.show()
            self.second_widget.setSizePolicy(
                QtWidgets.QSizePolicy.Preferred,
                QtWidgets.QSizePolicy.Preferred,
            )

        else:
            self.second_widget.hide()
            self.second_widget.setSizePolicy(
                QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored
            )
        wrapper = partial(self.resizeApp, 650, self.sizeHint().height())
        QtCore.QTimer.singleShot(0, wrapper)

    @QtCore.pyqtSlot(int, int)
    def resizeApp(self, width, height):
        self.resize(width, height)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)
    ex = App()
    ex.show()
    sys.exit(app.exec_())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...