首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多模型碰撞

多模型碰撞
EN

Stack Overflow用户
提问于 2014-09-26 00:44:56
回答 1查看 270关注 0票数 0

下面的代码创建一个窗口,左边是QListView,右边是QTableView。使用.setModel()QListView被指定为ListModelQTableView被指定为TableModel。在窗口启动时,只有列表视图才会填充这些项。只有单击左侧列表视图时,才会填充右表视图。

问:为什么这段代码会崩溃?是因为两种型号同时使用吗?

代码语言:javascript
复制
import sys, os
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 ListModel(QtCore.QAbstractTableModel):
    def __init__(self):
        QtCore.QAbstractTableModel.__init__(self) 
        self.items=[]    
    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.items) 
    def columnCount(self, index=QtCore.QModelIndex()):
        return 1        
    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()])
        if role==QtCore.Qt.UserRole:
            return key
        if role==QtCore.Qt.DisplayRole:
            return key

    def addItem(self, key=None, column=0):
        totalItems=self.rowCount()+1
        self.beginInsertRows(QtCore.QModelIndex(), totalItems, column)
        self.items.append(str(key))
        self.endInsertRows()

    def buildItems(self):
        for key in elements:
            self.addItem(key) 

class TableModel(QtCore.QAbstractTableModel):
    def __init__(self):
        QtCore.QAbstractTableModel.__init__(self)
        self.items=[]    
    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.items)
    def columnCount(self, index=QtCore.QModelIndex()):
        return 4
    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 key 

    def addItem(self, each=None, column=0):
        totalItems=self.rowCount()+1
        self.beginInsertRows(QtCore.QModelIndex(), totalItems, column)
        self.items.append(str(each))
        self.endInsertRows()

    def rebuildItems(self, index):
        key = index.data(QtCore.Qt.UserRole)
        if not key: return
        key=str(key.toString())
        for each in elements[key]:
            self.addItem(str(each)) 

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        mainLayout=QtGui.QHBoxLayout()
        self.setLayout(mainLayout) 
        self.dataModel=ListModel()
        self.dataModel.buildItems() 
        self.dataModelB=TableModel()
        self.viewA=QtGui.QListView()
        self.viewA.setModel(self.dataModel)
        self.viewA.clicked.connect(self.onClick) 
        self.viewB=QtGui.QTableView()         
        self.viewB.setModel(self.dataModelB)
        mainLayout.addWidget(self.viewA)
        mainLayout.addWidget(self.viewB)    
        self.show()
    def onClick(self, index):
        self.viewB.model().rebuildItems(index)

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

稍后编辑:

下面是一个固定的代码。在最初的例子中,这个问题是由于.beginInsertRows()方法使用不当造成的。我错误地认为要提供的最后一个参数是列号。但是根据文档(感谢three_pineapples指出),最后一个参数应该是要插入的最后一行号。

代码语言:javascript
复制
import os,sys
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 ListModel(QtCore.QAbstractTableModel):
    def __init__(self):
        QtCore.QAbstractTableModel.__init__(self) 
        self.items=[]    
    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.items) 
    def columnCount(self, index=QtCore.QModelIndex()):
        return 1        
    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()])
        if role==QtCore.Qt.UserRole:
            return key
        if role==QtCore.Qt.DisplayRole:
            return key

    def addItem(self, key=None):
        self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
        self.items.append(str(key))
        self.endInsertRows()

    def buildItems(self):
        for key in elements:
            self.addItem(key) 

class TableModel(QtCore.QAbstractTableModel):
    def __init__(self):
        QtCore.QAbstractTableModel.__init__(self)
        self.items=[]    
    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.items)
    def columnCount(self, index=QtCore.QModelIndex()):
        return 4
    def data(self, index, role):
        key=str(self.items[index.row()])
        column=index.column()

        if not index.isValid() or not (0<=index.row()<len(self.items)): return QtCore.QVariant()
        if role==QtCore.Qt.DisplayRole:
            if not column:  return key 
            else:
                print key, column, elements.get(key,{}).get(column)
                return elements.get(key,{}).get(column)

    def rebuildItems(self, index):
        key=index.data(QtCore.Qt.UserRole).toString()  

        self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
        self.items.append(key)
        self.endInsertRows()

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        mainLayout=QtGui.QHBoxLayout()
        self.setLayout(mainLayout) 
        self.dataModel=ListModel()
        self.dataModel.buildItems() 
        self.dataModelB=TableModel()
        self.viewA=QtGui.QListView()
        self.viewA.setModel(self.dataModel)
        self.viewA.clicked.connect(self.onClick) 
        self.viewB=QtGui.QTableView()         
        self.viewB.setModel(self.dataModelB)
        mainLayout.addWidget(self.viewA)
        mainLayout.addWidget(self.viewB)    
        self.show()
    def onClick(self, index):
        self.viewB.model().rebuildItems(index)

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

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-26 13:37:30

我无法在PyQt v4.11.1,32位Python2.7,Windows8.1上重现您的崩溃。

但是,您的TableModel实现已经完全崩溃,所以这大概可以解释为什么它会在Mac上崩溃?

具体地说:

  • beginInsertRows的签名似乎是错误的。它不遵循文档这里 (从QAbstractTableModel页面这里链接到)。签名不是beginInsertRows(parent, row, column),而是beginInsertRows(parent, row, numRows)
  • 当行索引从0开始时,要插入的行的值应该是self.rowCount()。因此,当模型中有0项时,可以插入到第0行(第一行)。当模型中有1项时,可以将其插入到第1行(第二行),等等。
  • TableModel.data()方法被破坏了。具体来说,它似乎缺少了行key=str(self.items[index.row()])

我的问题是,既然您似乎经常遇到模型问题(我觉得您在实现自定义模型方面遇到了很多问题),您为什么不使用预定义的Qt模型QStandardItemModel来完成所有复杂的工作呢?(使用它不需要子类)

如果您想要帮助您将上面发布的示例翻译为使用QStandardItemModel,请发布一个新的问题。我相信我或其他人都会很快回答的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26050341

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档