Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
181 views
in Technique[技术] by (71.8m points)

python 3.x - Pyside2: QSplitter replaceWidget not working as expected

I have a QSplitter with two widgets in it and want to replace one of them:

import sys
from PySide2.QtWidgets import (QMainWindow, QApplication, 
    QVBoxLayout, QWidget, QSplitter, QTextEdit, QLabel)


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

        splitter = QSplitter()
        splitter.insertWidget(0, QLabel('test'))
        splitter.insertWidget(1, QTextEdit())

        print(splitter.count())  # prints 2
        splitter.replaceWidget(1, QLabel('something else'))
        print(splitter.count())  # prints 1

        self.layout = QVBoxLayout(self)
        self.layout.addWidget(splitter)


if __name__ == "__main__":
    app = QApplication()

    main = Example()
    main.show()

    sys.exit(app.exec_())

My understanding of replaceWidget is that it will replace an existing widget on index X in the splitter by the provided widget. In the above example on index 0 there's a QLabel('test') and on index 1 QTextEdit().

After trying to replace the widget on index 1, I would expect it to be QLabel('something else'). But it seems that the widget on index 1 just gets deleted from looking at the output of the count() before and after the replace operation.

Can anyone see the issue?

question from:https://stackoverflow.com/questions/66062531/pyside2-qsplitter-replacewidget-not-working-as-expected

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This seems to be caused by a bug in PySide2. The count should be 2 after replaceWidget() is called, but it's 1.

According to the docs for replaceWidget, the splitter should take ownership of the new widget and reparent it. But PySide seems to lose track of it somehow - so presumably it just gets garbage-collected. The same code run in PyQt5 works as expected, although the inserted widget still won't show up (because reparenting will always make a widget invisble). The way to work around these issues is to make sure the widget has a parent before inserting it in the splitter, and then call show() on it afterwards:

    label = QLabel('something else', self)

    print(splitter.count())
    splitter.replaceWidget(1, label)
    print(splitter.count())

    label.show()

This works correctly for me in both PySide2 (5.15.2) and PyQt5 (5.15.2).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...