当窗口很小时按钮不可点击

问题描述

我正在创建一个可展开/可折叠的小部件,因为 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 演示效果

解决方法

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

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

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