下面的代码创建一个窗口,左侧为QListView
,右侧为QTableView
。 使用.setModel()
QListView
被指定为ListModel
并且QTableView
被指定为TableModel
。 在窗口启动时,只有列表视图会填充项目。只有当左侧列表视图被点击时,右表视图才会被填充。多个模型崩溃
问:为什么这个代码崩溃?是否因为两个模型同时使用?
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_())
LATER EDITED:
下面是一个固定的代码。在原始示例中,问题是由于使用方法不当造成的。我错误地认为要提供的最后一个参数是一个列号。但根据文档(感谢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_())
你能提供更多的崩溃细节吗?它在哪一行代码中发生? – Ezee 2014-09-26 09:39:48
在OSX上:10.7.5,Python:2.7.1,Qt:5.2.0,SIP:4.15.4,PyQt:4.10.4一旦左侧列表视图的项目被点击,它就会崩溃。 – alphanumeric 2014-09-26 17:53:04
你正在用PyQt4使用Qt5吗?除非你只是写错了,这似乎并不明智...... – 2014-09-27 02:34:55