Python 如何从multiselect QComboBox获取选中项?

Python 如何从multiselect QComboBox获取选中项?,python,pyqt,pyqt5,qcombobox,Python,Pyqt,Pyqt5,Qcombobox,我能够使用QComboBox和QStandardItemModel实现multi-select,但无法使用selectedItems()或checkedItems()选项获取所选项目,该选项会显示一条错误消息,显示为: AttributeError: 'QComboBox' object has no attribute 'selectedItems' AttributeError: 'QComboBox' object has no attribute 'chec

我能够使用QComboBox和QStandardItemModel实现multi-select,但无法使用selectedItems()或checkedItems()选项获取所选项目,该选项会显示一条错误消息,显示为:

AttributeError: 'QComboBox' object has no attribute 'selectedItems'               
AttributeError: 'QComboBox' object has no attribute 'checkedItems'
是否有办法获取QComboBox的选定项目列表? 下面是我的代码的示例实现

class CheckableComboBox(QComboBox):
    def __init__(self):
        super(CheckableComboBox, self).__init__()
        self.view().pressed.connect(self.handleItemPressed)
        self.setModel(QtGui.QStandardItemModel(self))

    def handleItemPressed(self, index):
        item = self.model().itemFromIndex(index)
        if item.checkState() == QtCore.Qt.Checked:
            item.setCheckState(QtCore.Qt.Unchecked)
        else:
            item.setCheckState(QtCore.Qt.Checked)

class Dialog_01(QMainWindow):
    def __init__(self):
        super(QMainWindow,self).__init__()       
        years = ["2017", "2018", "2019", "2020"]
        self.comboBoxv = QComboBox(self)
        self.model = QtGui.QStandardItemModel(self)
        firstItem = QtGui.QStandardItem("Select  Years")
        firstItem.setBackground(QtGui.QBrush(QtGui.QColor(200, 200, 200)))
        firstItem.setSelectable(False)
        self.model.setItem(0, 0, firstItem)
        for i,area in enumerate(years):
            item = QtGui.QStandardItem(area)
            item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
            item.setData(Qt.Unchecked, Qt.CheckStateRole)
            self.model.setItem(i+1, 0, item)
        self.comboBoxv.setModel(self.model)        
        self.comboBoxv.installEventFilter(self)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    dialog_1 = Dialog_01()
    dialog_1.show()
    dialog_1.resize(480,320)
    sys.exit(app.exec_())

checkedItems方法不存在,因此会出现该错误。解决方案是在模型上迭代,并验证是否选中了它

from PyQt5 import QtCore, QtGui, QtWidgets

class CheckableComboBox(QtWidgets.QComboBox):
    closedPopup = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(CheckableComboBox, self).__init__(parent)
        self.setView(QtWidgets.QListView(self))
        self.view().pressed.connect(self.handleItemPressed)
        self.setModel(QtGui.QStandardItemModel(self))

        firstItem = QtGui.QStandardItem("Select  Years")
        firstItem.setBackground(QtGui.QBrush(QtGui.QColor(200, 200, 200)))
        firstItem.setSelectable(False)
        self.model().appendRow(firstItem)

    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def handleItemPressed(self, index):
        item = self.model().itemFromIndex(index)
        if item.checkState() == QtCore.Qt.Checked:
            item.setCheckState(QtCore.Qt.Unchecked)
        else:
            item.setCheckState(QtCore.Qt.Checked)

    def checkedItems(self):
        l = []
        for i in range(self.model().rowCount()):
            it = self.model().item(i)
            if it.checkState() == QtCore.Qt.Checked:
                l.append(it.text())
        return l

    def hidePopup(self):
        self.closedPopup.emit()
        super(CheckableComboBox, self).hidePopup()
        QtCore.QTimer.singleShot(0, lambda: self.setCurrentIndex(0))

class Dialog_01(QtWidgets.QMainWindow):
    def __init__(self):
        super(Dialog_01,self).__init__()       
        years = ["2017", "2018", "2019", "2020"]
        self.comboBoxv = CheckableComboBox()
        self.comboBoxv.closedPopup.connect(self.on_closedPopup)
        for i, area in enumerate(years):
            item = QtGui.QStandardItem(area)
            item.setCheckable(True)
            item.setCheckState(QtCore.Qt.Unchecked)
            self.comboBoxv.model().appendRow(item)

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        lay = QtWidgets.QVBoxLayout(central_widget)
        lay.addWidget(self.comboBoxv)
        lay.addStretch()

    @QtCore.pyqtSlot()
    def on_closedPopup(self):
        print(self.comboBoxv.checkedItems())

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    dialog_1 = Dialog_01()
    dialog_1.show()
    dialog_1.resize(480,320)
    sys.exit(app.exec_())

checkedItems方法不存在,因此会出现该错误。解决方案是在模型上迭代,并验证是否选中了它

from PyQt5 import QtCore, QtGui, QtWidgets

class CheckableComboBox(QtWidgets.QComboBox):
    closedPopup = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(CheckableComboBox, self).__init__(parent)
        self.setView(QtWidgets.QListView(self))
        self.view().pressed.connect(self.handleItemPressed)
        self.setModel(QtGui.QStandardItemModel(self))

        firstItem = QtGui.QStandardItem("Select  Years")
        firstItem.setBackground(QtGui.QBrush(QtGui.QColor(200, 200, 200)))
        firstItem.setSelectable(False)
        self.model().appendRow(firstItem)

    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def handleItemPressed(self, index):
        item = self.model().itemFromIndex(index)
        if item.checkState() == QtCore.Qt.Checked:
            item.setCheckState(QtCore.Qt.Unchecked)
        else:
            item.setCheckState(QtCore.Qt.Checked)

    def checkedItems(self):
        l = []
        for i in range(self.model().rowCount()):
            it = self.model().item(i)
            if it.checkState() == QtCore.Qt.Checked:
                l.append(it.text())
        return l

    def hidePopup(self):
        self.closedPopup.emit()
        super(CheckableComboBox, self).hidePopup()
        QtCore.QTimer.singleShot(0, lambda: self.setCurrentIndex(0))

class Dialog_01(QtWidgets.QMainWindow):
    def __init__(self):
        super(Dialog_01,self).__init__()       
        years = ["2017", "2018", "2019", "2020"]
        self.comboBoxv = CheckableComboBox()
        self.comboBoxv.closedPopup.connect(self.on_closedPopup)
        for i, area in enumerate(years):
            item = QtGui.QStandardItem(area)
            item.setCheckable(True)
            item.setCheckState(QtCore.Qt.Unchecked)
            self.comboBoxv.model().appendRow(item)

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        lay = QtWidgets.QVBoxLayout(central_widget)
        lay.addWidget(self.comboBoxv)
        lay.addStretch()

    @QtCore.pyqtSlot()
    def on_closedPopup(self):
        print(self.comboBoxv.checkedItems())

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    dialog_1 = Dialog_01()
    dialog_1.show()
    dialog_1.resize(480,320)
    sys.exit(app.exec_())


如何在此处添加代码?请查看我已尝试在``之间插入代码,但它不允许我添加说明过多字符的注释相关信息(如代码)不应出现在注释中,而应出现在您的问题中,因此请编辑您的问题并在此处添加代码。在我的问题中添加代码,谢谢^i如何在此处添加代码?请查看我已尝试在``之间插入代码,但它不允许我添加注释,说明太多字符。相关信息(如代码)不应出现在注释中,而应出现在您的问题中,因此请编辑您的问题并在此处添加代码。在我的问题中添加代码,谢谢^i这很好,我想知道为什么下拉菜单在我选择项目之前不一直下拉,而不是每次选择时都关闭?@user9529330因为组合框的行为只是选择一个元素,如果你不想让它这样做,那么你必须修改该行为,因为你没有指出我不想更改它,您希望弹出窗口何时关闭?如果在我能够选择几个项目并单击下拉列表上的“上一步”后弹出窗口关闭,那就太好了。@user9529330单击用于检查一个项目,单击检查和关闭比较如何?我的意思是我希望下拉列表保持在下拉状态,以便我选择多个项目这很好,我想知道为什么下拉菜单在我选择项目之前不一直下拉,而不是每次选择时都关闭?@user9529330因为组合框的行为只是选择一个元素,如果你不想让它这样做,那么你必须修改该行为,因为你没有指出我不想更改它,您希望弹出窗口何时关闭?如果在我能够选择几个项目并在下拉列表上单击“上一步”后弹出窗口关闭,那就太好了。@user9529330单击用于检查一个项目,单击检查和关闭比较如何?我的意思是我希望下拉列表保持在下拉状态,以便我选择多个项目