QTableview checkitems,从对应的第二列获取值

QTableview checkitems, get value from corresponding second column

我有两个关于 QTableView 的问题。

  1. 如何使 QTable 只对第二列值可编辑,对第一列值只读?

  2. 如何获取勾选项的索引,从而获取勾选项对应的第二列的值?

    from PyQt5 import QtWidgets, QtGui
    
    class MyWidget(QtWidgets.QWidget):
    
        def __init__(self, parent=None):
            super().__init__(parent=parent)
    
            # selected items
            self.selected = []
            self.no       = []
    
            self.tableModel = QtGui.QStandardItemModel(self)
            self.tableModel.itemChanged.connect(self.itemChanged)
            # 
            item1 = QtGui.QStandardItem("file#1")
            item1.setCheckable(True)
            no1 = QtGui.QStandardItem("5.0")
            self.tableModel.appendRow([item1, no1])
            # 
            item2 = QtGui.QStandardItem("file#2")
            item2.setCheckable(True)
            no2 = QtGui.QStandardItem("23.0")
            self.tableModel.appendRow([item2, no2])
    
            self.mainLayout = QtWidgets.QVBoxLayout()
            self.setLayout(self.mainLayout)
    
            self.tableView = QtWidgets.QTableView()
            self.tableView.setModel(self.tableModel)
            self.mainLayout.addWidget(self.tableView)
    
            "First Question"
            """How to make table only editable second column, not firts:
               ex. can edit 23.0 or 5.0, but read only file names?
            """        
    
        def itemChanged(self, item):
            if item.checkState() != 0:
                if not item.text() in self.selected:
                    self.selected.append(item.text())
            else:
                if item.text() in self.selected:
                    self.selected.remove(item.text())
    
            print(self.selected)
    
            "Second Question"
            """How to get item checked index and to get the second column value:
               ex. file#2 has 23.0?
            """
    
            self.no.append(second column value) ****?
            print(self.no)
    
    def main():
        app = QtWidgets.QApplication([])
    
        mytable = MyWidget()
        mytable.show()
        app.exec_()
    
    if __name__ == "__main__":
        main()
    

这是两个不同的问题。我认为您应该单独询问他们并相应地修改您的问题。

第一个问题:如何制作专栏READ_ONLY?

为此,您必须定义自己的 QAbstractTableModel class 来定义一个名为 flags 的方法。这些标志将允许您根据需要更改单元格的属性。然后,您必须将新的 QAbstractTableModel 传递给 QTableView 并将其设置为新模型(这就像 QTableView 的后端)

from PyQt5.QtCore import Qt, QAbstractTableModel
from PyQt5.QtWidgets import QTableView, QApplication


class ParametersTableModel(QAbstractTableModel):

    def __init__(self):
        super(ParametersTableModel, self).__init__()
        self.headerText = ["Parameter 1", "Parameter 2"]
        self.data = [[1, 2], [1, 2]]

    def rowCount(self, parent=None):
        return len(self.data)

    def columnCount(self, parent=None):
        return len(self.headerText)

    def headerData(self, col, orientation, role):
        if role == Qt.DisplayRole:
            if orientation == Qt.Horizontal:
                return self.headerText[col]

    def data(self, index, role):
        if role == Qt.DisplayRole or role == Qt.EditRole:
            return self.data[index.row()][index.column()]

    def flags(self, index):
        if not index.isValid():
            return None
        else:
            if index.column() == 1:
                return Qt.ItemIsEnabled | Qt.ItemIsSelectable
            else:
                return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable


def main():
    app = QApplication([])
    tableModel = ParametersTableModel()
    tableView = QTableView()
    tableView.setModel(tableModel)
    tableView.show()
    app.exec_()


if __name__ == "__main__":
    main()

您可以随时查看 Qt 的文档以获得更深入的了解。 QTableView, QAbstractTableModel

如何让QTable只对第二列值可编辑,对第一列值只读?

有几种解决方案可以使项目成为一整列readonly/editable。

  • 修改标志,没有必要按照 的建议实现自定义模型,因为 QStandardItemModel 模型允许修改它们:

    # To make them editable:
    item.setEditable(True)
    # or
    # item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
    
    # To make them readonly:
    item.setEditable(False)
    # or
    # item.setFlags(item.flags() & ~QtCore.Qt.ItemIsEditable)
    
  • 使用委托的编辑器,因为默认情况下 QStandardItemModel 模型是可编辑的,所以只需要确定第 0 列是不可编辑的,为此你不应该生成编辑器:

    class ReadOnlyDelegate(QtWidgets.QStyledItemDelegate):
        def createEditor(self, parent, option, index):
            return
    
    delegate = ReadOnlyDelegate(self.tableView)
    self.tableView.setItemDelegateForColumn(0, delegate)
    

我更喜欢第二个选项,因为默认情况下它确定第一列是只读的。

如何获取勾选项的索引,从而获取勾选项对应的第二列的值?

泛型方法是先访问父亲,再访问同一行第二列的儿子:

parent_item = item.parent()
if parent_item is not None:
    second_item = parent_item.child(item.row(), 1)
else:
    second_item = item.model().item(item.row(), 1)
print(second_item.text())

但是你的情况可以简化为:

second_item = self.tableModel.item(item.row(), 1)
print(second_item.text())