【问题标题】:Checkboxes in a Combobox using PyQt使用 PyQt 的组合框中的复选框
【发布时间】:2011-07-10 17:04:32
【问题描述】:

我需要实现一个包含 CheckBox 的下拉列表,就像让 ComboBox 中的条目成为 CheckBox 一样。但是 QComboBox 不接受 QCheckBox 作为其成员,我找不到任何替代解决方案。我在 Qt Wiki 上的 C++ 中 found an implementation,但不知道如何将其移植到 python。

【问题讨论】:

    标签: python qt checkbox pyqt qcombobox


    【解决方案1】:

    使用 Combobox 项目模型,因为项目支持复选框 您只需要将项目标记为用户可检查,并设置初始 checkState 以使复选框出现(它仅在存在有效状态时显示)

    item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
    item.setCheckState(QtCore.Qt.Unchecked)  # causes checkBox to show
    

    这是一个最小的子类示例:

    from PyQt5 import QtGui, QtCore, QtWidgets
    import sys, os
    
    # subclass
    class CheckableComboBox(QtWidgets.QComboBox):
        # once there is a checkState set, it is rendered
        # here we assume default Unchecked
        def addItem(self, item):
            super(CheckableComboBox, self).addItem(item)
            item = self.model().item(self.count()-1,0)
            item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
            item.setCheckState(QtCore.Qt.Unchecked)
    
        def itemChecked(self, index):
            item = self.model().item(i,0)
            return item.checkState() == QtCore.Qt.Checked
    
    # the basic main()
    app = QtWidgets.QApplication(sys.argv)
    dialog = QtWidgets.QMainWindow()
    mainWidget = QtWidgets.QWidget()
    dialog.setCentralWidget(mainWidget)
    ComboBox = CheckableComboBox(mainWidget)
    for i in range(6):
        ComboBox.addItem("Combobox Item " + str(i))
    
    dialog.show()
    sys.exit(app.exec_())
    

    【讨论】:

      【解决方案2】:

      我已经在How do I create a tree view (with checkbox) inside a combo box - PyQt 回复了类似的问题,但无论如何,为了回复的完整性,我将您粘贴在这里:

      您应该创建一个模型,在 data 和 SetData 方法中支持 Qt.CheckStateRole,在 flags 方法中支持标志 Qt.ItemIsUserCheckable。

      我在这里粘贴一个我在项目中使用的示例,这是用于任何模型的 QSortFilterProxyModel 通用实现,但您可以在模型实现中使用相同的想法,显然我在您拥有的这个子类中使用内部结构不是直接在 PyQt 中,而是附加到我的内部实现(self.booleanSet 和 self.readOnlySet)。

      def flags(self, index):
          if not index.isValid():
              return Qt.ItemIsEnabled
      
          if index.column() in self.booleanSet:
              return Qt.ItemIsUserCheckable | Qt.ItemIsSelectable | Qt.ItemIsEnabled
          elif index.column() in self.readOnlySet:
              return Qt.ItemIsSelectable | Qt.ItemIsEnabled
          else:
              return QSortFilterProxyModel.flags(self, index)
      
      def data(self, index, role):
          if not index.isValid():
              return QVariant()
      
          if index.column() in self.booleanSet and role in (Qt.CheckStateRole, Qt.DisplayRole):
              if role == Qt.CheckStateRole:
                  value = QVariant(Qt.Checked) if index.data(Qt.EditRole).toBool() else QVariant(Qt.Unchecked)
                  return value
              else: #if role == Qt.DisplayRole:
                  return QVariant()
          else:
              return QSortFilterProxyModel.data(self, index, role)
      
      def setData(self, index, data, role):
          if not index.isValid():
              return False
      
          if index.column() in self.booleanSet and role == Qt.CheckStateRole:
              value = QVariant(True) if data.toInt()[0] == Qt.Checked else QVariant(False)
              return QSortFilterProxyModel.setData(self, index, value, Qt.EditRole)
          else:
              return QSortFilterProxyModel.setData(self, index, data, role)
      

      【讨论】:

      • 如果有人可以发布一个最小的工作示例,我个人会觉得非常有帮助。
      【解决方案3】:

      当我需要这个时,我想出了一个更简单的解决方案(至少不需要子类化 QCombobox)。它对我有用。 那就是创建一个带有可检查操作的菜单并将其设置为一个按钮。然后将菜单或操作连接到插槽。

      Qt 中的代码(还没有使用 PyQt,对不起,我希望你能移植那个,对我来说似乎更容易)是这样的:

      QMenu *menu = new QMenu;
      QAction *Act1 = new QAction("Action 1", menu);
      Act1->setCheckable(true);
      QAction *Act2 = new QAction("Action 2", menu);
      Act2->setCheckable(true);
      menu->addAction(Act1);
      menu->addAction(Act2);
      
      QPushButton *btn = new QPushButton("Btn");    
      btn->setMenu(menu);
      

      希望对你有帮助

      【讨论】:

      • 谢谢你,这是一个有用的答案,让我免于工作
      猜你喜欢
      • 2015-08-08
      • 1970-01-01
      • 2019-04-01
      • 2023-04-01
      • 1970-01-01
      • 2011-07-10
      • 2013-07-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多