window 小时按钮不可点击

Button is not clickable when window is small

我正在创建一个 expandable/collapsible 小部件,因为 Qt 直到现在才提供此类功能。我的问题是,如果 window 非常大(只有 window 的宽度相关),小部件 expand/collapse 的按钮似乎只能点击。主小部件的元素按预期工作。有谁知道原因吗?

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演示效果

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

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

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