如何启用/禁用基于事件的 QTreeView 中的项目?

Posted

技术标签:

【中文标题】如何启用/禁用基于事件的 QTreeView 中的项目?【英文标题】:How to enable/disable a item in a QTreeView eventbased? 【发布时间】:2012-03-11 09:09:43 【问题描述】:

我想在发送特定信号时启用/禁用 QTreeWidget 中的可检查项。

以下代码不起作用:

model = QStandardItemModel()
view = QTreeView()
view.setModel(model)
rootItem = QStandardItem()
rootItem = model.invisibleRootItem()

categoryItem = QStandardItem(item)
categoryItem.setCheckable(True)
rootItem.appendRow(categoryItem)

signalSource.availabilityChanged.connect(categoryItem.setEnabled)

它会产生错误:

TypeError: unhashable type: 'PySide.QtGui.QStandardItem'

有没有通过信号/槽改变 QStandardItem 的状态或数据的解决方案?

【问题讨论】:

你能发布完整的回溯和signalSource的定义吗? 【参考方案1】:

这看起来像是 PySide 中的一个错误,因为 connect 应该接受任何可调用的(示例代码在 PyQt4 中正常工作)。

作为一种解决方法,尝试将 QStandardItem 方法包装在 lambda 中:

signalSource.availabilityChanged.connect(
    lambda enable: categoryItem.setEnabled(enable))

编辑

要在循环中连接项目,请使用默认参数,如下所示:

for button in buttonList:
    item = QStandardItem("Test")
    ...
    button.toggled.connect(
        lambda enable, item=item: item.setEnabled(enable))

【讨论】:

谢谢。这帮助很大。 @leviathan。有关如何在循环中使用lambda,请参阅我的更新答案。【参考方案2】:

在 ekhumoros 回答的帮助下,我找到了解决问题的方法,但在 PySide 中这似乎是一个丑陋的解决方法,使用发送器来正确连接信号。

import sys
import argparse
import signal

#import sip
#sip.setapi('QString', 2)
#from PyQt4.QtGui import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QStandardItemModel, QStandardItem, QTreeView
from PySide.QtGui import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QStandardItemModel, QStandardItem, QTreeView


class MainWindow(QWidget):
    def __init__(self, parent=None):
              QWidget.__init__(self, parent)

              buttonList = []
              for i in xrange(10):
                  button = QPushButton("1")
                  button.setCheckable(True)
                  buttonList.append(button)

              model = QStandardItemModel()
              view = QTreeView()

              view.setModel(model)

              layout = QVBoxLayout()
              self.setLayout(layout)

              buttonLayout = QHBoxLayout()
              layout.addLayout(buttonLayout)

              for button in buttonList:
                  buttonLayout.addWidget(button)

              layout.addWidget(view)

              rootItem = QStandardItem()
              rootItem = model.invisibleRootItem()

              self.itemList = 
              for button in buttonList:
                  item = QStandardItem("Test")
                  item.setCheckable(True)
                  rootItem.appendRow(item)
                  self.itemList[button] = item

                  # Works with PyQt4, but not with PySide
                  #button.toggled.connect(item.setEnabled)
                  # Workaround for PySide
                  button.toggled.connect(self.workaround)

              for button in buttonList:
                  button.setChecked(True)


          def workaround(self, enable):
              self.itemList[self.sender()].setEnabled(enable)


def main(argv):
    app = QApplication(argv)
    w = MainWindow()
    w.show()
    retcode = app.exec_()


if __name__ == "__main__":
    main(sys.argv)

仅使用 lambda 构造在循环中不起作用。它只是将所有信号与最后一个引用连接起来进行迭代。

【讨论】:

以上是关于如何启用/禁用基于事件的 QTreeView 中的项目?的主要内容,如果未能解决你的问题,请参考以下文章

Angular 9 中基于条件/事件的启用/禁用复选框

jsp点击一个按钮后禁用按钮,执行完事件后再启用按钮

如何禁用 UITextView 中的复制、粘贴选项并再次启用 iPhone 应用程序?

QTreeView - 如何判断拖放事件是重新排序还是父母之间的移动?

如何基于选择表单启用和禁用垫按钮

如何在回收站视图上启用和禁用拖放