如何在调整大小时隐藏 QTreeWidget 中的 QWidgets?
How to keep QWidgets in QTreeWidget hidden during resize?
我在 QTreeWidget 中有一个简单的 UI 和 QWidgets。
其中一些需要隐藏。
每次调整应用程序大小时,所有 QWidget 都会变得可见。
下面是演示该问题的最小示例。
在显式调用 setVisible(True)
之前,如何确保 QWidgets 保持隐藏状态?
pyqt版本是5.12.3
from PyQt5.QtWidgets import QApplication, QWidget, QTreeWidgetItem, QTreeWidget, QCheckBox, QPushButton, QVBoxLayout
import sys
class Foo(QWidget):
def __init__(self):
super().__init__()
lay = QVBoxLayout(self)
tree = QTreeWidget()
item = QTreeWidgetItem()
tree.addTopLevelItem(item)
self.checkBox = QCheckBox()
tree.setItemWidget(item,0,self.checkBox)
button = QPushButton('Hide Checkbox')
button.clicked.connect(self.hideCheckbox)
lay.addWidget(tree)
lay.addWidget(button)
lay.addWidget(button)
def hideCheckbox(self):
self.checkBox.setVisible(False) # is reset on resize
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())
考虑到这是由调用项视图的 private updateEditorGeometries()
函数引起的,只要视图更新其内容的几何形状,它就会自动显示索引小部件,对此没有直接控制。
不过,有两种可能的解决方法。
将项目小部件添加到容器
在这种情况下,项目小部件是一个基本的 QWidget,充当 actual 小部件的容器。由于 show()
只会在项目小部件上调用,显式隐藏子小部件将避免问题:
self.checkBox = QCheckBox()
container = QWidget()
containerLayout = QHBoxLayout(container)
containerLayout.setContentsMargins(0, 0, 0, 0)
containerLayout.addWidget(self.checkBox)
tree.setItemWidget(item, 0, container)
请注意,将内容边距设置为 0 很重要(否则将添加默认的 Qt 布局边距)。
在 QTreeWidget 子类中覆盖 updateGeometries()
updateGeometries()
在项目视图调整大小时或视口内容需要内部更改(columns/rows 调整大小、模型已更改等)时由项目视图调用。
您可以创建 QTreeWidget 的子类,保留为项目设置的内部小部件列表,然后在调用基本实现之前跟踪隐藏的小部件:
class TreeWidget(QTreeWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.itemWidgets = set()
def setItemWidget(self, item, column, widget):
self.itemWidgets.add(widget)
widget.destroyed.connect(lambda: self.itemWidgets.discard(widget))
super().setItemWidget(item, column, widget)
def updateGeometries(self):
hidden = [w for w in self.itemWidgets if w.isHidden()]
super().updateGeometries()
for widget in hidden:
widget.setVisible(False)
我在 QTreeWidget 中有一个简单的 UI 和 QWidgets。
其中一些需要隐藏。
每次调整应用程序大小时,所有 QWidget 都会变得可见。
下面是演示该问题的最小示例。
在显式调用 setVisible(True)
之前,如何确保 QWidgets 保持隐藏状态?
pyqt版本是5.12.3
from PyQt5.QtWidgets import QApplication, QWidget, QTreeWidgetItem, QTreeWidget, QCheckBox, QPushButton, QVBoxLayout
import sys
class Foo(QWidget):
def __init__(self):
super().__init__()
lay = QVBoxLayout(self)
tree = QTreeWidget()
item = QTreeWidgetItem()
tree.addTopLevelItem(item)
self.checkBox = QCheckBox()
tree.setItemWidget(item,0,self.checkBox)
button = QPushButton('Hide Checkbox')
button.clicked.connect(self.hideCheckbox)
lay.addWidget(tree)
lay.addWidget(button)
lay.addWidget(button)
def hideCheckbox(self):
self.checkBox.setVisible(False) # is reset on resize
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())
考虑到这是由调用项视图的 private updateEditorGeometries()
函数引起的,只要视图更新其内容的几何形状,它就会自动显示索引小部件,对此没有直接控制。
不过,有两种可能的解决方法。
将项目小部件添加到容器
在这种情况下,项目小部件是一个基本的 QWidget,充当 actual 小部件的容器。由于 show()
只会在项目小部件上调用,显式隐藏子小部件将避免问题:
self.checkBox = QCheckBox()
container = QWidget()
containerLayout = QHBoxLayout(container)
containerLayout.setContentsMargins(0, 0, 0, 0)
containerLayout.addWidget(self.checkBox)
tree.setItemWidget(item, 0, container)
请注意,将内容边距设置为 0 很重要(否则将添加默认的 Qt 布局边距)。
在 QTreeWidget 子类中覆盖 updateGeometries()
updateGeometries()
在项目视图调整大小时或视口内容需要内部更改(columns/rows 调整大小、模型已更改等)时由项目视图调用。
您可以创建 QTreeWidget 的子类,保留为项目设置的内部小部件列表,然后在调用基本实现之前跟踪隐藏的小部件:
class TreeWidget(QTreeWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.itemWidgets = set()
def setItemWidget(self, item, column, widget):
self.itemWidgets.add(widget)
widget.destroyed.connect(lambda: self.itemWidgets.discard(widget))
super().setItemWidget(item, column, widget)
def updateGeometries(self):
hidden = [w for w in self.itemWidgets if w.isHidden()]
super().updateGeometries()
for widget in hidden:
widget.setVisible(False)