有没有一种方法可以检查PyQt5表中已选中了哪些复选框

时间:2019-03-30 20:58:38

标签: python pyqt pyqt5 qtablewidget qtablewidgetitem

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

我已经通过PyQt5设计器创建了表格,在表格的每个空间中都具有如下复选框:

enter image description here

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)

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

抱歉,这似乎是一个基本问题-预先感谢

3 个答案:

答案 0 :(得分: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_())

答案 1 :(得分:1)

只需修改上面的代码!

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

self._checked_items = []

2)在“ book_clicked”方法添加行内:

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

3)声明一个checked_items的吸气剂:

def checked_items(self):
    return self._checked_items

4)在主要方法中打印checked_items:

print(w.checked_items())

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

当然,起初看起来比较复杂,但是后来,当您了解如何使用基于模型的小部件时,您会喜欢的!

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

答案 2 :(得分:1)

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

主窗口。

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