从 Pyqt5 中的可检查组合框中获取已检查的文本

Posted

技术标签:

【中文标题】从 Pyqt5 中的可检查组合框中获取已检查的文本【英文标题】:get checked text from checkable combobox in Pyqt5 【发布时间】:2018-06-19 07:31:06 【问题描述】:

我正在尝试从使用 pyqt5 中的复选框创建的自定义组合框中收集选中项目的文本。

这是我的可行 sn-p,它没有按照我的期望打印选定的文本:

from PyQt5 import QtCore, QtGui, QtWidgets
import sys

class CheckableComboBox(QtWidgets.QComboBox):
    def __init__(self, parent = None):
        super(CheckableComboBox, self).__init__(parent)
        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)

    def checkedItems(self):
        checkedItems = []
        for index in range(self.count()):
            item = self.item(index)
            if item.checkState() == Qt.Checked:
                checkedItems.append(item)
        return checkedItems

class Ui_dialogCreateBatch(object):
    def setupUi(self, dialogCreateBatch):
        dialogCreateBatch.resize(400, 338)
        dialogCreateBatch.setMouseTracking(True)

        self.gridLayoutWidget = QtWidgets.QWidget(dialogCreateBatch)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 10, 360, 115))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")

        self.cboItemList = CheckableComboBox(self.gridLayoutWidget)
        self.cboItemList.setObjectName("cboItemList")
        self.gridLayout.addWidget(self.cboItemList, 0, 0, 1, 1)

        data = ('item1', 'item2', 'item3')
        for index, element in enumerate(data):
            self.cboItemList.addItem(element)
            item = self.cboItemList.model().item(index, 0)
            item.setCheckState(QtCore.Qt.Unchecked)

        self.buttonBox = QtWidgets.QDialogButtonBox(dialogCreateBatch)
        self.buttonBox.setGeometry(QtCore.QRect(100, 300, 156, 23))
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)

        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")

        self.retranslateUi(dialogCreateBatch)

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(dialogCreateBatch.reject)
        QtCore.QMetaObject.connectSlotsByName(dialogCreateBatch)

    def retranslateUi(self, dialogCreateBatch):
        _translate = QtCore.QCoreApplication.translate
        dialogCreateBatch.setWindowTitle(_translate("dialogCreateBatch", "Create Item Batch"))

    def accept(self):
        selectedItems = self.cboItemList.checkedItems()
        print(selectedItems)
        dialogCreateBatch.close

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    dialogCreateBatch = QtWidgets.QDialog()
    ui = Ui_dialogCreateBatch()
    ui.setupUi(dialogCreateBatch)
    dialogCreateBatch.show()
    sys.exit(app.exec_())

在上面的代码中,我添加了用于记录返回数据的打印行。但我没有收到从这里返回的任何数据

提前致谢

【问题讨论】:

【参考方案1】:

就我而言,当我执行您的代码时,我看不到QCheckBox,解决方案是在QComboBoxview() 上建立一个QListView

我看到的最大错误是,在下面的表达式self.cboMulSup.checkedItems() 中,您试图访问cboMulSup,但您从未定义它。

另一方面,不建议修改 Qt Designer 生成的代码,PyQt 我建议创建另一个继承自相应小部件的类并使用类Ui_xxx

from PyQt5 import QtCore, QtGui, QtWidgets
import sys

class CheckableComboBox(QtWidgets.QComboBox):
    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))

    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):
        checkedItems = []
        for index in range(self.count()):
            item = self.model().item(index)
            if item.checkState() == QtCore.Qt.Checked:
                checkedItems.append(item)
        return checkedItems

class Ui_dialogCreateBatch(object):
    def setupUi(self, dialogCreateBatch):
        dialogCreateBatch.resize(400, 338)
        dialogCreateBatch.setMouseTracking(True)

        self.gridLayoutWidget = QtWidgets.QWidget(dialogCreateBatch)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 10, 360, 115))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")

        self.cboItemList = CheckableComboBox(self.gridLayoutWidget)
        self.cboItemList.setObjectName("cboItemList")
        self.gridLayout.addWidget(self.cboItemList, 0, 0, 1, 1)

        data = ('item1', 'item2', 'item3')

        for index, element in enumerate(data):
            self.cboItemList.addItem(element)
            item = self.cboItemList.model().item(index, 0)
            item.setCheckState(QtCore.Qt.Unchecked)

        self.buttonBox = QtWidgets.QDialogButtonBox(dialogCreateBatch)
        self.buttonBox.setGeometry(QtCore.QRect(100, 300, 156, 23))
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)

        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")

        self.retranslateUi(dialogCreateBatch)
        QtCore.QMetaObject.connectSlotsByName(dialogCreateBatch)

    def retranslateUi(self, dialogCreateBatch):
        _translate = QtCore.QCoreApplication.translate
        dialogCreateBatch.setWindowTitle(_translate("dialogCreateBatch", "Create Item Batch"))

class DialogCreateBatch(QtWidgets.QDialog, Ui_dialogCreateBatch):
    def __init__(self, parent=None):
        QtWidgets.QDialog.__init__(self, parent)
        self.setupUi(self)
        self.buttonBox.accepted.connect(self.on_accepted)
        self.buttonBox.rejected.connect(self.reject)

    def on_accepted(self):
        selectedItems = self.cboItemList.checkedItems()
        print(selectedItems)
        self.accept()

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = DialogCreateBatch()
    w.show()
    sys.exit(app.exec_())

【讨论】:

谢谢!我已经添加了它可以工作的 QListView。对于 cboMulSup,这是我在折射时的错误,我应该改变它。你建议我不要编辑 Qt Designer,因为我缺乏 Qt Designer 知识,我无法实现这个可检查的组合框。 我很困惑为什么我们需要再使用一个类DialogCreateBatch。这是为了保持自定义组合框和 ui_Dialog 对象集成? 如果你能帮助我保持下拉菜单的显示,允许用户从列表中选择更多,直到他/她移动到下一个,这将更完整。

以上是关于从 Pyqt5 中的可检查组合框中获取已检查的文本的主要内容,如果未能解决你的问题,请参考以下文章

如何在组合框中获取已选中的单选按钮?

PyQt5:根据选择的元素与数据框中的另一个元素匹配设置自定义组合框文本的字体颜色

Excel VBA检查各种组合框中是不是存在值,然后添加相应的文本框值

如何检查 html 文本框中给出的 php 中的数据类型?

if语句检查文本框中的字符数

使用正则表达式检查字符串和整数的组合