python - 如何访问存储在 QModelIndex 中的数据

标签 python qt pyqt

下面的代码创建了一个“附加”了数据和代理模型的QListView。 单击其中一个单选按钮调用 buttonClicked() 函数。

此函数调用模型的.data(index,role) 方法来获取存储在当前索引中的数据。

对于 DisplayRole,模型的 .data() 方法正确返回索引的名称(在创建索引时分配给它)。但是当
使用了“ItemDataRole”我收到错误消息:

TypeError: QSortFilterProxyModel.data(QModelIndex, int role=Qt.DisplayRole): argument 2 has unexpected type 'sip.enumtype'

--

Question 1: How to fix this error?

如果你看一下 addItems() 方法,那里有一行:

self.setData(index, 'keyword')

显然,我正在尝试将“关键字”设置为我自己的“自定义数据”(过滤索引时将使用 ProxyModel 吗?)。

问题2:如何查询我用self.setData(index, 'keyword')设置的字符串“keyword”? 这些数据是可访问的还是“保留的”且无法查询?

enter image description here

from PyQt4 import QtCore, QtGui
app=QtGui.QApplication(sys.argv)
elements={'Animals':{1:'Bison',2:'Panther',3:'Elephant'},'Birds':{1:'Duck',2:'Hawk',3:'Pigeon'},'Fish':{1:'Shark',2:'Salmon',3:'Piranha'}}

class ProxyModel(QtGui.QSortFilterProxyModel):
    def __init__(self, parent=None):
        super(ProxyModel, self).__init__(parent)

class DataModel(QtCore.QAbstractListModel):
    def __init__(self):
        QtCore.QAbstractListModel.__init__(self)
        self.items=[] 
    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.items)
    def data(self, index, role):
        if not index.isValid() or not (0<=index.row()<len(self.items)):  return QtCore.QVariant()

        if role==QtCore.Qt.DisplayRole:
            return self.items[index.row()]

        elif role==QtCore.Qt.ItemDataRole:
            return index.data()

    def addItems(self):
        for key in elements:
            index=QtCore.QModelIndex()
            self.setData(index, 'keyword')
            self.beginInsertRows(index, 0, 0)
            self.items.append(key)           

        self.endInsertRows()        

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        layout=QtGui.QVBoxLayout()
        self.setLayout(layout)        

        self.view=QtGui.QListView()

        self.dataModel=DataModel()        
        self.dataModel.addItems()

        self.proxyModel=ProxyModel()
        self.proxyModel.setSourceModel(self.dataModel)
        self.view.setModel(self.proxyModel)
        buttonsLayout=QtGui.QHBoxLayout()
        animalsButton=QtGui.QRadioButton('Show Animals')
        birdsButton=QtGui.QRadioButton('Show Birds')
        fishButton=QtGui.QRadioButton('Show Fish')
        self.buttons=[animalsButton,birdsButton,fishButton]
        for button in self.buttons:
            button.toggled.connect(self.buttonClicked)
            buttonsLayout.addWidget(button)      
        layout.addWidget(self.view)
        layout.insertLayout(1,buttonsLayout)
        self.show()

    def buttonClicked(self,arg=None):
        for button in self.buttons:
            if button.isChecked(): break

        index=self.view.currentIndex()
        print 'Index DisplayRole: %s'%self.view.model().data(index, QtCore.Qt.DisplayRole).toString() 
        # print 'ItemDataRole', self.view.model().data(index, QtCore.Qt.ItemDataRole)    

window=Window()
sys.exit(app.exec_())

最佳答案

这是一个关于如何使用 QTableView 的工作示例与 QStandardItemModel填充了 QStandardItem

使用 QtGui.QStandardItemModel 的可能优势在 QtCore.QAbstractListModel是那个QtGui.QStandardItemModel不必为了分配给 QTableView 而进行子分类. 您只需继续声明即可:

view=QtGui.QTableView() # declare table view
model=QtGui.QStandardItemModel() # declare model
view.setModel(model) # assign model to table view

要创建一个 View 项,首先声明它:

item=QtGui.QStandardItem('My Item Name') # stored 'My Item Name' can be queried using `Qt.DisplayRole` flag

分配声明的 QStandardItem查看使用:

model.appendRow(item)

model.appendRow(item)方法“创造”了尽可能多的QModelIndex es 因为 TableView 中有列。所以不需要创建QModelIndex es 手动为一行中的每一列:项目分配到的行。

接下来使用 item.setData(value,role)您可以使用预定义的方法之一存储任何类型的数据 QModelIndex角色如:

item.setData('< Column 0 My Display Value as "DisplayRole" >', QtCore.Qt.DisplayRole)
item.setData('< Column 0 My Custom Value as "UserRole" >', QtCore.Qt.UserRole)
item.setData('< Column 0 My Custom Value as "UserRole+1" >', QtCore.Qt.UserRole+1)

上面的所有三个赋值行都用于为同一个“项目”分配三个不同的值:第一个值是一个字符串 '< Column 0 My Display Value as "DisplayRole" >'存储在 Qt.DisplayRole 下角色(使用此角色将其取回)。

字符串值:'< Column 0 My Custom Value as "UserRole" >'存储在 Qt.UserRole 下.使用此角色将其取回。等等

同时 item.setData(value,role)方法非常有用,它确实使用简单的语法它也非常有限,因为它只处理单个 QModelIndex存储在项目分配到的行的零列中。为了能够存储存储在项目行的非零列中的自定义数据(或修改现有数据),我们首先获取项目的行号:

itemRow=item.row()

知道项目的行号,我们可以使用 在“手动”模式下:

indexOfColumn1=model.index(itemRow, 1)
indexOfColumn2=model.index(itemRow, 2)

(其中第二个整数参数,例如 12 是列号)。

或者在“全自动”模式下:

for i in range(model.columnCount()):
    eachColumnIndex=model.index(itemRow, i)

了解项目的 QModelIndexes我们可以像使用 item.setData() 一样使用它们来查询或存储数据方法(仅从/向零列 QModelIndex 分配/检索数据的方法)。

为了存储和检索每列中的数据- QModelIndex我们必须使用 model.setData(index,value,role)model.data(index, role)方法(看来我们不能直接使用 QModelIndex 实例获取/设置数据...像这样:

myIndex.setData(value,role) - 这是自 QModelIndex 以来的无效代码不附带 .setData()方法。

为了检索每个 QModelIndex 存储的数据我们使用 model.data(index,role) :

model=view.model()
print model.data(index, QtCore.Qt.UserRole+1).toPyObject() 

对于单列 View (例如 .QListView )处理提供的 QStandardItem方法可能就足够了。但是对于多列 View (例如 QTabLeView,有可能必须访问单个列的 QModelIndexe

enter image description here

import os,sys
home=os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
sys.path.append(os.path.join(home,'site-packages'))
from PyQt4 import QtCore, QtGui
app=QtGui.QApplication(sys.argv)
class Window(QtGui.QTableView):
    def __init__(self):
        super(Window, self).__init__() 
        model=QtGui.QStandardItemModel()

        model.setHorizontalHeaderLabels(['Column 0','Column 1','Column 3'])
        for i in range(3):
            item=QtGui.QStandardItem('Column 0 Item %s'%i)
            item.setData('< Column 0 Custom Value as "UserRole" >', QtCore.Qt.UserRole)
            item.setData('< Column 0 Custom Value as "UserRole+1" >', QtCore.Qt.UserRole+1)
            model.appendRow(item)

            itemRow=item.row()
            indexOfColumn1=model.index(itemRow, 1)
            indexOfColumn2=model.index(itemRow, 2)

            model.setData(indexOfColumn1, 'Column 1 Item', QtCore.Qt.DisplayRole)
            model.setData(indexOfColumn1, '< Column 1 Custom Value as "UserRole" >', QtCore.Qt.UserRole)

            model.setData(indexOfColumn2, 'Column 2 Item', QtCore.Qt.DisplayRole)
            model.setData(indexOfColumn2, '< Column 2 Custom Value as "UserRole" >', QtCore.Qt.UserRole)

        self.setModel(model)
        self.clicked.connect(self.onClick)  
        self.show()

    def onClick(self,index=None):
        row=index.row()
        column=index.column()

        model=self.model()
        indexOfColumn0=model.index(row, 0)
        indexOfColumn1=model.index(row, 1)
        indexOfColumn2=model.index(row, 2)
        print indexOfColumn0==index, indexOfColumn1==index, indexOfColumn2==index


        print  'ROW: %s  COLUMN: %s'%(row,column)
        print 'DispayRoleData via self.model().data(index,role): "%s"'%self.model().data(index, QtCore.Qt.DisplayRole).toString()
        print 'UserRoleData via self.model().data(index,role): "%s"'%self.model().data(index, QtCore.Qt.UserRole).toPyObject()
        print 'UserRoleData via self.model().data(index,role): "%s"'%self.model().data(index, QtCore.Qt.UserRole+1).toPyObject()      

        for key in self.model().itemData(index):
            print 'self.model.itemData(index):    key: %s  value: %s'%(key, self.model().itemData(index)[key].toString())

        item=self.model().itemFromIndex(index)


window=Window()
sys.exit(app.exec_())

关于python - 如何访问存储在 QModelIndex 中的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25943153/

相关文章:

php - int((0.1+0.7)*10) = 7 在多种语言中。如何防止这种情况?

c++ - macOS上缺少Qt库

c++ - 更改 QT 上的主窗口内容

python - PyQt4-QNativeImage : Unable to attach to shared memory segment

android - 安卓上的 PyQt

python - 如何使用占位符分配 tf.Variables?

python - 如何在 Keras 中使用高级激活层?

python - 有效地删除 *index* 包含空值的数据帧行 (NaT)

c++ - 调用 qdecimal 库函数

winforms - 父窗口未收到窗口消息(关键事件)