Какой метод PyQt является предпочтительным (эффективным) для контроля размера окна и настройки макетов?

У меня есть сетка элементов в PyQt, и когда пользователь изменяет размер окна, мне нужно соответственно увеличить/уменьшить количество столбцов. Количество строк обрабатывается областью прокрутки, поэтому мне не нужно беспокоиться об изменениях в направлении y (если это имеет значение).

В моей реализации QMainWindow я знаю, что можно переопределить функцию resizeEvent(), которая будет запускаться для любых и всех настроек окна. Однако использовать это для перестроения сетки каждый раз ужасно неэффективно. Просто чтобы проверить функцию, чтобы увидеть, как она работает, я заставил resizeEvent просто напечатать строку, и это привело к тому, что мои настройки окна были немного запаздывающими и визуально несовершенными (скорее дрожащими, чем плавными). Я, вероятно, выполню простую операцию деления размера окна, чтобы увидеть, стало ли оно больше или меньше, чтобы изменить количество столбцов, но даже это, если выполнять сотни раз за настройку, может вызвать проблемы с задержкой. Перестроение всей сетки может занять даже секунду, поэтому было бы предпочтительнее не делать этого, пока пользователь манипулирует окном.

Есть ли более эффективный способ сделать это, или resizeEvent мой единственный вариант? В идеале я хотел бы, чтобы событие срабатывало только после того, как пользователь закончил настройку окна, а не событие, которое срабатывает практически для каждого движения пикселя по мере их возникновения (которое может быть сотни или тысячи раз за регулировку в течение 1 секунды) .

Я использую PyQt5, но если вы лучше знакомы с PyQt4, я могу понять ваше решение PyQt4 в контексте PyQt5. То же самое для решения C++ Qt4/5.


person user3525381    schedule 26.04.2014    source источник
comment
Очень заинтересован в этом, и я сам реализовал что-то подобное, переопределив resizeEvent, и да, это немного отстает. Это не очень хороший код (написанный, когда я впервые начал программировать в PySide), но он может быть полезен в качестве эталона для тех, кто пытается реализовать что-то лучше. Код находится здесь: bitbucket.org/labscript_suite/labscript_utils/ источник/   -  person three_pineapples    schedule 26.04.2014


Ответы (2)


Похоже, единственная реальная проблема заключается в обнаружении завершения изменения размера. Пока это тщательно контролируется, фактический макет может быть выполнен любым способом, который вам нравится.

Ниже приведено решение, использующее таймер для управления моментом испускания сигнала о завершении изменения размера. Он не тормозит, но я не тестировал его с какими-либо сложными макетами (хотя все должно быть в порядке).

from PyQt4 import QtCore, QtGui

class Window(QtGui.QWidget):
    resizeCompleted = QtCore.pyqtSignal()

    def __init__(self):
        QtGui.QWidget.__init__(self)
        self._resize_timer = None
        self.resizeCompleted.connect(self.handleResizeCompleted)

    def updateResizeTimer(self, interval=None):
        if self._resize_timer is not None:
            self.killTimer(self._resize_timer)
        if interval is not None:
            self._resize_timer = self.startTimer(interval)
        else:
            self._resize_timer = None

    def resizeEvent(self, event):
        self.updateResizeTimer(300)

    def timerEvent(self, event):
        if event.timerId() == self._resize_timer:
            self.updateResizeTimer()
            self.resizeCompleted.emit()

    def handleResizeCompleted(self):
        print('resize complete')

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 300, 300, 300)
    window.show()
    sys.exit(app.exec_())
person ekhumoro    schedule 26.04.2014
comment
Я был бы заинтересован в методе handleResizeCompleted, если вы все еще здесь. Я пытался вычислить коэффициент (текущий размер окна / начальный размер окна), который затем умножит x, y, width, height или все мои виджеты, а также, возможно, их размер шрифта. Проблема заключается в том, чтобы найти размер окна. Любая идея об этом? :) - person Guimoute; 05.11.2019
comment
Ничто из того, что я пробовал / читал сегодня, не сработало. self.window().size() остается постоянным, когда я изменяю размер окна, точно так же, как self.size() и self.geometry(). - person Guimoute; 05.11.2019
comment
@Guimoute Пожалуйста, начните новый вопрос и предоставьте минимальный воспроизводимый пример. - person ekhumoro; 05.11.2019

Я думаю, вам нужен FlowLayoutfot для этой цели, который автоматически регулирует количество столбцов при изменении размера виджета, содержащего его. Здесь находится документация для FlowLayout и здесь — это версия PyQt того же макета.

person qurban    schedule 26.04.2014
comment
Спасибо за предложение, к сожалению, кажется, что FlowLayout был удален в PyQt5. Попытка использовать его привела к ошибке атрибута, поэтому я проверил документацию, и ее нигде нет. pyqt.sourceforge.net/Docs/PyQt5/class_reference.html - person user3525381; 26.04.2014