【问题标题】:Is there a way to check which check boxes have been checked in a PyQt5 table有没有办法检查在 PyQt5 表中选中了哪些复选框
【发布时间】:2026-01-13 22:10:01
【问题描述】:

我正在尝试使用桌子制作房间预订系统。在表格中我有复选框,我希望这样当用户单击图书按钮时,程序会看到哪些复选框已被选中,以便它可以从表格中删除这些复选框。

我通过 PyQt5 设计器创建了表格,表格的每个空间都有复选框,如下所示:

UI 文件代码有很多这样的行:

        item = QtWidgets.QTableWidgetItem()
        item.setFlags(QtCore.Qt.ItemIsUserCheckable|QtCore.Qt.ItemIsEnabled)
        item.setCheckState(QtCore.Qt.Unchecked)
        self.tableWidget.setItem(0, 0, item)
        item = QtWidgets.QTableWidgetItem()
        item.setFlags(QtCore.Qt.ItemIsUserCheckable|QtCore.Qt.ItemIsEnabled)
        item.setCheckState(QtCore.Qt.Unchecked)
        self.tableWidget.setItem(0, 1, item)

这是否意味着复选框都称为项目?有没有一种方法可以为每个复选框单独命名?

抱歉,这似乎是一个基本问题 - 提前致谢

【问题讨论】:

  • 复选框的名称是什么?
  • 我不确定,正如我所说我在 PyQt 设计器中设计的,所以我使用了 QTableWidget,双击它,转到项目、属性,然后在标志下检查用户 Checkable。跨度>
  • 不,我想你不理解我,你想识别复选框所以我想知道你想从项目中获取什么数据,在我的回答中我建议打印行的标签和列

标签: python pyqt pyqt5 qtablewidget qtablewidgetitem


【解决方案1】:

您必须遍历表并检查每个项目的状态,使用过滤后的项目,您可以获得带有标签的行和列。

from PyQt5 import QtCore, QtGui, QtWidgets

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        self.tableWidget = QtWidgets.QTableWidget(6, 5)
        self.book_button = QtWidgets.QPushButton("Book")
        self.book_button.clicked.connect(self.book_clicked)

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.tableWidget)
        lay.addWidget(self.book_button)

        self.tableWidget.setHorizontalHeaderLabels("P1 P2 P3 P4 P5 P6".split())
        self.tableWidget.setVerticalHeaderLabels("C101 C214 C320 F04 E201".split())

        for i in range(self.tableWidget.rowCount()):
            for j in range(self.tableWidget.columnCount()):
                item = QtWidgets.QTableWidgetItem()
                item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
                item.setCheckState(QtCore.Qt.Unchecked)
                self.tableWidget.setItem(i, j, item)

    @QtCore.pyqtSlot()
    def book_clicked(self):
        items = []
        for i in range(self.tableWidget.rowCount()):
            for j in range(self.tableWidget.columnCount()):
                item = self.tableWidget.item(i, j)
                if item.checkState() == QtCore.Qt.Checked:
                    items.append(item)

        for it in items:
            r = it.row()
            c = it.column()
            v, h = self.tableWidget.horizontalHeaderItem(c).text(), self.tableWidget.verticalHeaderItem(r).text()
            print(h, v)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

【讨论】:

  • 我怎样才能拥有它,而不是打印 (h, v),而是将它们添加到单个数组或列表中,然后作为一个打印。
  • 在此之后我将如何删除复选框
【解决方案2】:

只需对上面的代码稍作修改!

1) 在构造函数中声明空列表值。

self._checked_items = []

2) 在 'book_clicked' 方法内添加一行:

self._checked_items.append([h, v])

3) 声明一个checked_items的getter:

def checked_items(self):
    return self._checked_items

4) 在main方法中打印checked_items:

print(w.checked_items())

但我建议你使用 QTableView(),而不是 QTableWidget()。 QTableWidget() 是基于项目的,QTableView() 是基于模型的。

当然,第一次它看起来更复杂,但后来,当您了解如何使用基于模型的小部件时,您会喜欢它!

您要做的是实现自定义 CheckedItemsModel ,它扩展了 QAbstractItemModel。查看文档,您会发现很多示例。

【讨论】:

    【解决方案3】:

    我为你做了,你很幸运)))

    主窗口。

    from PyQt5 import QtWidgets
    from PyQt5.QtWidgets import QHeaderView
    
    from examples.checkedItemsModel import CheckedItemsModel
    from examples.checkedItemsUI import Ui_CheckedItemsView
    
    class CheckedItems(QtWidgets.QMainWindow):
        def __init__(self, model= None, parent = None):
            super(CheckedItems, self).__init__(parent)
    
            self._ui = Ui_CheckedItemsView()
            self._ui.setupUi(self)
    
            self._model = model
    
            self._ui.ui_table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
            self._ui.ui_table_view.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
    
            # set the table model
            self._ui.ui_table_view.setModel(self._model)
    
            # create connecitons
            self._ui.btn_book.clicked.connect(self.print_checked_items)
    
        def print_checked_items(self):
            model = self._ui.ui_table_view.model()
    
            items = model.checkedItems()
            self._ui.ui_result.setPlainText(str(items))
            print(items)
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
    
        # data for table creation
        column_headers = ['P1', 'P2', 'P3', 'P4', 'P5', 'P6']
        row_headers = ['C101', 'C214', 'C320', 'F04', 'E201']
    
        # create table model
        model = CheckedItemsModel(column_headers, row_headers)
    
        # pass model to custom widget
        w = CheckedItems(model)
        w.show()
    
        sys.exit(app.exec_())
    

    模型的实现:

    import typing
    from PyQt5 import QtCore
    from PyQt5.QtCore import QAbstractTableModel, Qt, QModelIndex
    
    
    class CheckedItemsModel(QAbstractTableModel):
        def __init__(self, column_headers= [], row_headers=[], parent = None):
            super(CheckedItemsModel, self).__init__(parent)
    
            self._column_headers = column_headers
            self._row_headers = row_headers
    
            # create all unchecked items by default
            self._items = []
            for i in range(len(self._row_headers)):
                self._items.append([])
                for j in range(len(self._column_headers)):
                    self._items[i].append(Qt.Unchecked)
    
        def rowCount(self, parent: QModelIndex = QtCore.QModelIndex()) -> int:
            return len(self._row_headers)
    
        def columnCount(self, parent: QModelIndex = ...) -> int:
            return len(self._column_headers)
    
        def data(self, index: QModelIndex, role: int = QtCore.Qt.DisplayRole) -> typing.Any:
            if role == QtCore.Qt.DisplayRole:
                return ''#str(index.row()) + ', ' + str(index.column())
    
            if role == QtCore.Qt.CheckStateRole:
                if self._items[index.row()][index.column()] == Qt.Checked:
                    return QtCore.Qt.Checked
                else:
                    return QtCore.Qt.Unchecked
    
        def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any:
            if role == QtCore.Qt.DisplayRole:
                if orientation == Qt.Horizontal:
                    return self._column_headers[section]
                else:
                    return self._row_headers[section]
    
        def setData(self, index: QModelIndex, value: typing.Any, role: int = QtCore.Qt.EditRole) -> bool:
            if role == Qt.EditRole:
                self._items[index.row()][index.column()] = value
                self.dataChanged.emit(index, index)
    
                return True
    
            if role == Qt.CheckStateRole:
                self._items[index.row()][index.column()] = value
                self.dataChanged.emit(index, index)
    
                return True
    
        def flags(self, index: QModelIndex):
            return Qt.ItemIsUserCheckable | Qt.ItemIsEnabled
    
        def checkedItems(self):
            items = []
    
            for i in range(self.rowCount()):
                for j in range(self.columnCount()):
                    if self._items[i][j] == QtCore.Qt.Checked:
                        items.append('(' + str(self._row_headers[i]) + ', ' + str(self._column_headers[j]) + ')')
    
            return items
    

    以及来自 Qt Designer 的 View 类(自动将 .ui 文件转换为 .py):

    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file 'ui_CheckedItems.ui'
    #
    # Created by: PyQt5 UI code generator 5.9.2
    #
    # WARNING! All changes made in this file will be lost!
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    class Ui_CheckedItemsView(object):
        def setupUi(self, CheckedItemsView):
            CheckedItemsView.setObjectName("CheckedItemsView")
            CheckedItemsView.resize(685, 470)
            self.centralwidget = QtWidgets.QWidget(CheckedItemsView)
            self.centralwidget.setObjectName("centralwidget")
            self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
            self.horizontalLayout.setObjectName("horizontalLayout")
            self.verticalLayout = QtWidgets.QVBoxLayout()
            self.verticalLayout.setObjectName("verticalLayout")
            self.ui_table_view = QtWidgets.QTableView(self.centralwidget)
            sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
            sizePolicy.setHorizontalStretch(0)
            sizePolicy.setVerticalStretch(0)
            sizePolicy.setHeightForWidth(self.ui_table_view.sizePolicy().hasHeightForWidth())
            self.ui_table_view.setSizePolicy(sizePolicy)
            self.ui_table_view.setMinimumSize(QtCore.QSize(200, 200))
            self.ui_table_view.setObjectName("ui_table_view")
            self.verticalLayout.addWidget(self.ui_table_view)
            self.ui_result = QtWidgets.QTextEdit(self.centralwidget)
            self.ui_result.setReadOnly(True)
            self.ui_result.setObjectName("ui_result")
            self.verticalLayout.addWidget(self.ui_result)
            self.buttonsLayout = QtWidgets.QHBoxLayout()
            self.buttonsLayout.setObjectName("buttonsLayout")
            spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
            self.buttonsLayout.addItem(spacerItem)
            self.btn_book = QtWidgets.QPushButton(self.centralwidget)
            self.btn_book.setObjectName("btn_book")
            self.buttonsLayout.addWidget(self.btn_book)
            spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
            self.buttonsLayout.addItem(spacerItem1)
            self.verticalLayout.addLayout(self.buttonsLayout)
            self.verticalLayout.setStretch(0, 5)
            self.verticalLayout.setStretch(1, 1)
            self.horizontalLayout.addLayout(self.verticalLayout)
            CheckedItemsView.setCentralWidget(self.centralwidget)
    
            self.retranslateUi(CheckedItemsView)
            QtCore.QMetaObject.connectSlotsByName(CheckedItemsView)
    
        def retranslateUi(self, CheckedItemsView):
            _translate = QtCore.QCoreApplication.translate
            CheckedItemsView.setWindowTitle(_translate("CheckedItemsView", "MainWindow"))
            self.btn_book.setText(_translate("CheckedItemsView", "Book"))
    

    How the program look like, when you execute

    【讨论】:

      最近更新 更多