1

我正在创建一个可扩展/可折叠的小部件,因为 Qt 直到现在才提供这样的功能。我的问题是,展开/折叠小部件的按钮似乎只能点击,如果你让窗口非常大(只有窗口的宽度是相关的)。主小部件的元素按预期工作。有谁知道它的原因?

import sys
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton, QLabel, QMainWindow, QVBoxLayout, QHBoxLayout, QToolButton
from PyQt5.QtCore import Qt


class ExpandableWidget(QWidget):
    '''A widget that can be expanded / collapsed by the user'''

    def __init__(self):
        super(ExpandableWidget, self).__init__()
        
        self.titleWidget = QWidget() # widget containing the title bar (always visible)
        self.mainWidget = QWidget()  # widget containing the collapsible content (sometimes visible, but this isn't implemented yet)

        self.expandButton = QToolButton()
        self.expandButton.setCheckable(True)
        self.expandButton.setChecked(False)
        self.expandButton.setArrowType(Qt.LeftArrow)

        self.titleLayout = QHBoxLayout()
        self.titleLayout.addWidget(self.titleWidget)
        self.titleLayout.addWidget(self.expandButton)

        self.wrapperLayout = QVBoxLayout()
        self.wrapperLayout.addLayout(self.titleLayout)
        self.wrapperLayout.addWidget(self.mainWidget)

        self.setLayout(self.wrapperLayout)

    def setMainWidget(self, widget):
        self.wrapperLayout.replaceWidget(self.mainWidget, widget)
        self.mainWidget = widget

    def setTitleWidget(self, widget):
        self.titleLayout.replaceWidget(self.titleWidget, widget)
        self.titleWidget = widget


if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWindow = QMainWindow()

    expandable = ExpandableWidget()
    mainWindow.setCentralWidget(expandable)

    mainWidget = QPushButton("Button")
    titleLabel = QLabel("Title Label")

    expandable.setTitleWidget(titleLabel)
    expandable.setMainWidget(mainWidget)

    mainWindow.show()
    sys.exit(app.exec_())

GIF 演示效果

4

1 回答 1

2

一个小部件在布局中替换另一个小部件并不意味着第二个小部件将被删除或隐藏,而是该小部件不会由布局处理。因此,在您的情况下,旧小部件位于按钮上,导致点击不会传输到新按钮。

在您的情况下,一个可能的解决方案是删除默认小部件。

def setMainWidget(self, widget):
    self.wrapperLayout.replaceWidget(self.mainWidget, widget)
    if self.mainWidget.parent() is self:
        self.mainWidget.deleteLater()
    else:
        self.mainWidget.setParent(None)
    self.mainWidget = widget

def setTitleWidget(self, widget):
    self.titleLayout.replaceWidget(self.titleWidget, widget)
    if self.titleWidget.parent() is self:
        self.titleWidget.deleteLater()
    else:
        self.titleWidget.setParent(None)
    self.titleWidget = widget
于 2021-04-14T21:31:32.213 回答