多个模型崩溃

时间:2014-09-26 00:44:57

标签: python qt pyqt

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

enter image description here

问题:为什么这段代码会崩溃?是因为两个型号在同一时间使用吗?

enter image description here

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指出),最后一个参数应该是要插入的最后一个行号。

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_()) 

1 个答案:

答案 0 :(得分:2)

我无法在PyQt v4.11.1,32位Python 2.7,Windows 8.1上重现您的崩溃。

但是,你的TableModel实现完全被破坏了,所以可能会解释为什么它在你的Mac上崩溃了?

具体做法是:

  • beginInsertRows的签名似乎有误。它没有关注文档here(链接到QAbstractTableModel页面here)。签名不是beginInsertRows(parent, row, column),而是beginInsertRows(parent, row, numRows)

  • 要插入的行的值应为self.rowCount(),因为行索引从0开始。因此,当模型中有0个项目时,将插入到第0行(第一行)。如果模型中有1个项目,则插入第1行(第2行)等。

  • TableModel.data()方法已损坏。具体来说,似乎缺少行key=str(self.items[index.row()])

我的问题是,因为你似乎经常遇到模型问题(我觉得我在这里看到很多关于实现自定义模型的问题),为什么不是?你使用预定义的Qt模型QStandardItemModel为你做了所有复杂的事情吗? (您不需要将其子类化以使用它)

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