使用PyQt,监控窗口大小及调整布局的首选(高效)方法是什么?

6 投票
2 回答
1346 浏览
提问于 2025-04-18 04:19

我在PyQt中有一个物品的网格,当用户调整窗口大小时,我需要相应地增加或减少列的数量。行的数量是通过一个滚动区域来处理的,所以我不需要担心垂直方向的变化(如果这有影响的话)。

在我实现的QMainWindow中,我知道可以重写resizeEvent()这个函数,它会在窗口调整时被触发。不过,每次都用这个函数来重建网格效率太低了。为了测试这个函数的效果,我让resizeEvent只是打印一个字符串,这样导致我的窗口调整时有点卡顿,视觉效果也不太好(看起来抖动而不是流畅)。我可能会对窗口大小进行简单的除法运算,看看它是否变大或变小到需要改变列数的程度,但即使这样,每次调整时运行一百次也可能会造成卡顿。重建整个网格可能需要一秒钟,所以最好在用户调整窗口时不需要这样做。

有没有更有效的方法,还是说resizeEvent是我唯一的选择?理想情况下,我希望有一个事件只在用户完成窗口调整后触发,而不是在他们每移动一个像素时就触发(这在一秒内可能会发生几百到几千次)。

我使用的是PyQt5,但如果你更熟悉PyQt4,我可以在PyQt5的上下文中理解你的PyQt4解决方案。C++的Qt4/5解决方案也是一样的。

2 个回答

0

我觉得你需要用到一个叫做 FlowLayout 的布局,它可以根据你调整的窗口大小,自动改变列的数量。这里FlowLayout 的相关文档,而这里

5

看起来唯一真正的问题是如何判断调整大小是否完成。只要这个过程控制得当,实际的布局方式可以随你喜欢。

下面是一个解决方案,它使用定时器来控制何时发出调整大小完成的信号。看起来没有延迟,但我还没有用复杂的布局进行测试(不过应该没问题)。

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_())

撰写回答