QSplitter.sizes 表示尺寸错误

QSplitter.sizes indicates wrong sizes

我这样保存我的一个 QSplitter 的状态:

self.options.setValue("Window/final_splitter", self.splitter2.saveState())

然后我就这样恢复了:

self.splitter2.restoreState(self.options.value("Window/final_splitter"))

当我保存分离器时,splitter2.sizes()表示:[321, 818, 769]

当我恢复分离器时,它在视觉上与我关闭它时的尺寸相同,但 splitter2.sizes() 表示:[224, 572, 537]

而且我无法对分离器执行更多操作,因为我无法获得正确的尺寸。

你知道如何解决这个错误吗?

编辑: 更奇怪的是:

节省:

self.options.setValue("Window/final_splitter", self.splitter2.sizes())

-> self.splitter2.sizes(): [321, 844, 743]

正在恢复:

sizes_splitter2 = [int(nbr) for nbr in self.options.value("Window/final_splitter", [])]
self.splitter2.setSizes(sizes_splitter2)

编辑 2: 当我保存拆分器时,我也这样做(自己是一个 QMainWIndow):

self.options.setValue("window_geometry", self.saveGeometry())
self.options.setValue("window_state", self.saveState())

如果我评论这些行,splitter.sizes() returns 好的值。 但是这两行完成了它们的工作,window 被它们恢复到正确的大小!

.restoreState()documentation 表示您必须将 returned 值重新转换为 ByteArrayQSettings 可以 return Variant类型,和你原来设置的类型不一样。

self.splitter.restoreState(self.options.value("final_splitter").toByteArray())

值得注意的是,QSettings 的行为在不同版本的 PyQt/PySide 和不同平台上略有不同,但以上内容应该适用于所有情况。

我猜你想在 window 完全显示之前查询拆分器大小。

解决此问题的一种方法是在事件循环启动后使用单发计时器执行进一步的操作。

希望这个演示脚本能够展示正在发生的事情:

from PyQt4 import QtCore, QtGui

class Window(QtGui.QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        widget = QtGui.QWidget(self)
        layout = QtGui.QVBoxLayout(widget)
        self.setCentralWidget(widget)
        self.splitter = QtGui.QSplitter(self)
        self.splitter.addWidget(QtGui.QTextEdit(self))
        self.splitter.addWidget(QtGui.QTextEdit(self))
        self.splitter.addWidget(QtGui.QTextEdit(self))
        self.button = QtGui.QPushButton('Test', self)
        self.button.clicked.connect(lambda: self.printSizes('Test'))
        layout.addWidget(self.splitter)
        layout.addWidget(self.button)
        self.printSizes('Show Before')
        settings = self.settings()
        value = settings.value('splitter')
        if value is not None:
            self.splitter.restoreState(value)
        value = settings.value('layout')
        if value is not None:
            self.restoreState(value)
        value = settings.value('geometry')
        if value is not None:
            self.restoreGeometry(value)
        self.printSizes('Show After')
        QtCore.QTimer.singleShot(
            20, lambda: self.printSizes('Timer'))

    def closeEvent(self, event):
        self.printSizes('Close')
        settings = self.settings()
        settings.setValue("splitter", self.splitter.saveState())
        settings.setValue("geometry", self.saveGeometry())
        settings.setValue("layout", self.saveState())

    def settings(self):
        return QtCore.QSettings(
            QtCore.QSettings.IniFormat,
            QtCore.QSettings.UserScope, 'test', 'test')

    def printSizes(self, message):
        print('%s:' % message)
        print('  window geometry:', (
            self.width(), self.height(), self.x(), self.y()))
        print('  splitter sizes:', self.splitter.sizes())
        print()

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())