【问题标题】:QSplitter.sizes indicates wrong sizesQSplitter.sizes 表示尺寸错误
【发布时间】:2015-03-01 15:27:43
【问题描述】:

我这样保存我的一个 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)
  • sizes_splitter2:[321、844、743]
  • self.splitter2.sizes(): [224, 590, 519]

编辑 2: 当我保存拆分器时,我也会这样做(self 是 QMainWIdow):

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

如果我评论这些行,splitter.sizes() 会返回好的值。 但是这两条线完成了他们的工作,窗口与它们一起恢复到正确的大小!

【问题讨论】:

  • 在拆分器上调用.refresh() 有帮助吗?文档提到您不需要这样做,但它可能会有所帮助。
  • 不,没有任何改变,抱歉。
  • 感谢您的澄清。这很奇怪,无法解释。
  • 我注意到321+818+769=1908 和224+572+537=1333。如果您使用321/1908=0.168 和224/1333=0.168。也就是说第一个区域仍然占据了 16.8% 的窗口,只是窗口更小了。这是真的吗?
  • 是的,我也开始闻到什么味道了。我对我的问题添加了编辑。但没有窗户不小。当我关闭和打开我的程序时,一切都完全一样。

标签: python pyqt qsplitter


【解决方案1】:

我猜您正在尝试在窗口完全显示之前查询拆分器大小。

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

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

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

【讨论】:

  • 不是真的,我正在尝试获取拆分器的大小来调整大小。但实际上,我的拆分器的尺寸比应有的小,但它们显示正常。 size() 方法返回错误的结果。此外,MainWindow.geometry() 返回的宽度小于窗口实际的宽度。
  • @Rififi。我的示例按预期工作。如果你有反例,你需要在你的问题中展示它。
  • QtCore.QTimer.singleShot(0, lambda: print('Timer:', self.splitter.sizes())) 应该打印拆分器的实际大小?
  • @Rififi。是的,它适用于我在 Linux 上。使用 python 3.4.2、qt 4.8.6、pyqt 4.11.3。你的设置是什么?
  • @Rififi。我扩展了我的示例以使用保存/恢复状态/几何的QMainWindow,这一切都按我的预期工作。如果您需要更多帮助,您将不得不制作一个重现问题的工作示例。
【解决方案2】:

.restoreState() 的documentation 表示必须将返回值重铸为ByteArray(QSettings 可以返回Variant 类型,与您最初设置的类型不同)。

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

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

【讨论】:

  • 我试过:self.splitter2.restoreState(self.options.value("Window/final_splitter").toByteArray()),但我有一个异常告诉我它已经是一个byteArray。拆分器尺寸在窗口中视觉上已恢复,但似乎其大小属性设置不正确。
  • 是的,我想知道当设置它们时 UI 是否正在更新但它不是 ByteArray 阻止它在内部存储它。哦,好吧,回到绘图板。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-12
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多