当多个视图共享单个模型时 [英] When single model is shared by multiple views

查看:46
本文介绍了当多个视图共享单个模型时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有两个视图:

listView=QtGui.QListView()
tableView==QtGui.QTableView() 

我继续定义一个自定义 DataModel 以供 listViewtableView 使用:

I go ahead and define a custom DataModel to be used by both listView and tableView:

class DataModel(QtCore.QAbstractTableModel):
    def __init__(self):
        QtCore.QAbstractTableModel.__init__(self)
        self.data=[['One':'Two'],['Three','Four']]

def data(self, index, role):
    row=index.row()
    if requested by listView:
        return self.data[row][0]
    elif requested by tableView:
        return self.data[row][1]

最后将模型的实例分配给两个视图:

Finally assigning the instance of the model to both views:

model=DataModel()
listView.setModel(model)
tableView.setModel(model)

由于两个视图共享相同的模型,因此模型可能需要根据请求的视图小部件返回不同的值.如果您查看 data() 方法,则有假的 if/elif 语句显示了我需要的内容.有什么方法可以从模型方法内部执行此逻辑:if Requested by ListView...elif requests by TableView

Since both views share the same model there is a chance the model would need to return different values based on what view widget is requesting it. If you take a look at data() method there is fake if/elif statement showing what I need. Is there any way to do this logic from inside of model methods: if requested by ListView... and elif requested by TableView

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

class DataModel(QtCore.QAbstractTableModel):
    def __init__(self):
        QtCore.QAbstractTableModel.__init__(self)
        self.modelDict={}    
        self.items=[]    
    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.items)   

    def columnCount(self, index=QtCore.QModelIndex()):
        return 3

    def data(self, index, role):
        if not index.isValid() or not (0<=index.row()<len(self.items)): return QtCore.QVariant()
        key=str(self.items[index.row()])
        column=index.column()

        if role==QtCore.Qt.ItemDataRole: return self.modelDict.get(str(index.data().toString()))

        if role==QtCore.Qt.DisplayRole:
            if column==0 and not self.columnCount():
                return key
            else:
                return self.modelDict.get(key).get(column)  

    def addItem(self, itemName=None, column=0):
        totalItems=self.rowCount()+1
        self.beginInsertRows(QtCore.QModelIndex(), totalItems, column)
        if not itemName:            itemName='Item %s'%self.rowCount()
        self.items.append(itemName)
        self.endInsertRows()

    def buildItems(self):
        for key in self.modelDict:
            index=QtCore.QModelIndex()
            self.addItem(key) 

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

    def headerData(self, column, orientation, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.TextAlignmentRole:
            if orientation == QtCore.Qt.Horizontal:
                return QtCore.QVariant(int(QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter))
            return QtCore.QVariant(int(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter))
        if role != QtCore.Qt.DisplayRole:
            return QtCore.QVariant()

        if orientation==QtCore.Qt.Horizontal:
            if column==0:
                return QtCore.QVariant("Spicie 0")
            elif column==1:
                return QtCore.QVariant("Spicie 1")
            elif column==2:
                return QtCore.QVariant("Spicie 2")

        return QtCore.QVariant(int(column + 1))

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        mainLayout=QtGui.QHBoxLayout()
        self.setLayout(mainLayout)   

        self.dataModel=DataModel()
        self.dataModel.modelDict=elements
        self.dataModel.buildItems() 

        self.proxyModel=ProxyTableModel()
        self.proxyModel.setFilterKeyColumn(0)    
        self.proxyModel.setSourceModel(self.dataModel)

        self.viewA=QtGui.QListView()
        self.viewA.setModel(self.dataModel)
        self.viewA.clicked.connect(self.onClick)          
        self.viewB=QtGui.QTableView() 
        self.viewB.setModel(self.proxyModel)

        mainLayout.addWidget(self.viewA)
        mainLayout.addWidget(self.viewB)    
        self.show()

    def onClick(self):
        index=self.viewA.currentIndex()
        key=self.dataModel.data(index, QtCore.Qt.DisplayRole)  
        value=self.dataModel.data(index, QtCore.Qt.ItemDataRole)        
        self.proxyModel.setFilterRegExp('%s'%key)
        print 'onClick(): key: %s'%key

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

推荐答案

完成,隐藏第零个键"列:

Done, by hiding the zeroth "key" column:

class DataModel(QtCore.QAbstractTableModel):
    def __init__(self):
        QtCore.QAbstractTableModel.__init__(self)
        self.modelDict={}    
        self.names=[]    
    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.names)   
    def columnCount(self, index=QtCore.QModelIndex()):
        return 4

    def data(self, index, role):
        if not index.isValid() or not (0<=index.row()<len(self.names)): return QtCore.QVariant()
        row,col = index.row(),index.column()
        if col==0:
            if role==QtCore.Qt.DisplayRole: 
                return self.names[row]
        else:
            if role==QtCore.Qt.DisplayRole: 
                return self.modelDict[self.names[row]][col]

    def addItem(self, itemName=None, column=0):
        totalItems=self.rowCount()+1
        self.beginInsertRows(QtCore.QModelIndex(), totalItems, column)
        if not itemName:            itemName='Item %s'%self.rowCount()
        self.names.append(itemName)
        self.endInsertRows()

    def buildItems(self):
        for key in self.modelDict:
            index=QtCore.QModelIndex()
            self.addItem(key) 

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

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        mainLayout=QtGui.QHBoxLayout()
        self.setLayout(mainLayout)   

        self.dataModel=DataModel()
        self.dataModel.modelDict=elements
        self.dataModel.buildItems() 

        self.proxyModel=ProxyModel()
        self.proxyModel.setFilterKeyColumn(0)    
        self.proxyModel.setSourceModel(self.dataModel)

        self.viewA=QtGui.QListView()
        self.viewA.setModel(self.dataModel)
        self.viewA.clicked.connect(self.onClick)          
        self.viewB=QtGui.QTableView() 
        self.viewB.setModel(self.proxyModel)
        self.viewB.setColumnHidden(0,True)

        mainLayout.addWidget(self.viewA)
        mainLayout.addWidget(self.viewB)    
        self.show()

    def onClick(self):
        index=self.viewA.currentIndex()
        key=self.dataModel.data(index, QtCore.Qt.DisplayRole)  
        self.proxyModel.setFilterRegExp('%s'%key)

这篇关于当多个视图共享单个模型时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆