QListView理论上能够和全部QAbstractItemModel派生的类如QStringListModel、QDirModel、QFileSystemModel、QStandardItemModel等对接,但QListView实际上能展现的数据仅一列,对于复杂的树形层次使用Model使用QListView来展示意义不大。本节经过几个简单代码案例来阐述QListView/Model开发的过程。html
QStringListModel是Qt提供的一个已经实现QAbstractItemModel相关接口的Model,适合于展现一系列字符串的简单视图如QListView对象和QComboBox对象。python
QStringListModel提供了全部可编辑模型的标准函数,将字符串列表中的数据存储为一个一列多行的模型。web
使用index(int row, int column = 0, QModelIndex parent = QModelIndex())函数获取与项对应的模型索引,使用flags(QModelIndex index)获取项标志;使用data()函数读取项数据,并使用setData()写入项数据,使用rowCount()函数访问模型数据的行数。编程
该模型能够用现有的字符串列表来构造,或者能够用setStringList()函数来设置字符串。字符串也能够用insertRows()函数以一般的方式插入,并用removeRows()删除。字符串列表的内容可使用stringList()函数检索。windows
使用QStringListModel做为QListView的Model的方法很是简单,先建立QStringListModel实例对象,若是数据未存储到Model中则将数据存储到Model,而后再将QListView对象的Model设置为刚建立的Model实例。步骤以下:浏览器
实例对象建立有两种方法:架构
若是建立的model中无数据,能够经过几种方法初始化model中的数据:app
self.model1.setStringList(["item1", "item2", "item3", "item4", "item5", "item6", "item7", "item8", "item9", "item10"])
使用insertRows()、index()、setData()方法组合实现
insertRows是在model中插入空的数据记录,只是占据了数据位置,但没有实际的数据,须要经过setData来生成实际存储的数据。这种组合方法没有多大实际价值,具体方法的参数及含义在此不进行详细介绍。svg
使用视图的setModel(model)方法将model和view创建链接函数
本示例代码使用先建立对象再使用setStringList方法初始化数据:
def initStringListModel(self): strList = ["item1", "item2", "item3", "item4", "item5", "item6", "item7", "item8", "item9", "item10"] self.model = QStringListModel() self.model.setStringList(strList ) self.listView.setModel(self.model)
运行截图:
QFileSystemModel提供了将本地文件系统中指定目录文件结构树形文件列表的进行存储的model类,它提供对本地文件系统的访问,提供重命名和删除文件和目录以及建立新目录的功能。在最简单的状况下,它能够做为浏览器或过滤器的一部分与适当的显示部件一块儿使用。
虽然QListView是单层次的视图,QFileSystemModel是树形层次的model,但仍是能够在QListView中使用相似QFileSystemModel这种树状层次数据Model。只是视图展现时只会展现最顶层的数据,所以实际意义不大。
使用QFileSystemModel来做为QListView的model很是简单,只有三步就能够实现:
建立QFileSystemModel对象
使用setRootPath设置QFileSystemModel对应文件的目录路径
使用视图的setModel(model)方法将model和view创建链接
def initDirModel(self): self.model = QtWidgets.QFileSystemModel() self.model.setRootPath(r"c:\temp")#监视目录异动 self.listView.setModel(self.model) self.listView.setRootIndex(self.model.index(r"c:\temp"))()))#切换显示目录
运行截图:
QStandardItemModel是Model/View架构中用于存储自定义数据的通用Model,它提供了一种经典的基于项的方法来处理模型,模型中的项类型必须是QStandardItem类或其派生子类。
QStandardItemModel实现QAbstractItemModel定义的接口,这意味着该模型能够用于在任何支持该接口的视图(例如QListView、QTableView和QTreeView,以及本身的自定义视图)中提供数据。为了实现性能和灵活性,须要对从QAbstractItemModel模型派生子类,以提供对不一样类型的数据存储的支持,例如,QDirModel为底层文件系统提供一个模型接口。
因为QStandardItemModel是一个通用的Model,使用它做为视图的Model实现起来比相似QFileSystemModel等便利化专用化的Model要稍微复杂,其复杂主要是数据初始化方面。具体实现步骤以下:
建立Model对象
可使用QStandardItemModel(parent: QObject = None)、QStandardItemModel(int rowCount, int columnCount, parent: QObject = None)来建立Model对象。
初始化数据
初始化数据时,须要每一个数据建立一个QStandardItem或其派生类的对象,并将其加入到Model中去。QStandardItem类有四个构造方法QStandardItem()、QStandardItem(str text)、QStandardItem(QIcon icon, str text)、QStandardItem(int rows, int columns = 1),分别用于建立单个空项、一个带数据的项、一个带图标和数据的项、多个空项,对于空项还须要使用setText(QVariant value, int role = Qt.UserRole + 1)等方法设置项存储的数据。
使用视图的setModel(model)方法将model和view创建链接
def initStandItemModel(self): self.model = QStandardItemModel() strList = ["item1", "item2", "item3", "item4", "item5", "item6", "item7", "item8", "item9", "item10"] row = 0 for itemStr in strList: item = StandardItem(itemStr) self.model.setItem(row, 0, item) row += 1 self.listView.setModel(self.model)
运行截图:
QListView的modelColumn属性用于控制视图中展示model中哪一列数据,缺省值为0,即展示第一列数据。
能够经过modelColumn()、setModelColumn(int column)来访问和设置该属性。但Qt Designer中该属性值只能为0,没法设置为非0,这是由于QListView只显示一列数据,通常状况下若是使用的Model没有多列数据的话,是无需设置modelColumn属性,但并非不能使用多列数据的Model。如上面第三部分使用QFileSystemModel与QListView配合使用。
下面是一个使用QStandardItemModel建立的一个6行5列的Model与QListView配合使用的初始化代码:
def initMultiColumnModel(self): self.model = QStandardItemModel() for row in range(6): for col in range(5): item = StandardItem("row: {row},col: {col}".format(row=row + 1, col=col + 1)) self.listView.setModel(self.model)
如使用QFileSystemModel来测试,发现能够经过setModelColumn来调整显示的数据内容,而后又改为了QStandardItemModel,使用model的setItem方法来设置多列数据,也可使用setModelColumn来调整显示数据。
多列模式的Model初始化后显示的是第一列数据,若是要调整显示其余列的数据,能够经过setModelColumn来调整显示列。
在视图中的项不但能够展现文字,也能够展现图标和复选框,同时能够指定项是否能够拖拽、选择、编辑。有两种方法支持在项中展现图标。
下面的代码支持将指定目录的图象文件的文件名和图象在视图中展现:
def initIconModel(self): self.model = QStandardItemModel() ICon1 = QStandardItem(QIcon(r"F:\学习\python\资源\图像文件\add.png"),'add.png') ICon2 = QStandardItem(QIcon(r"F:\学习\python\资源\图像文件\application_windows_add.png"), 'application_windows_add.png') ICon3 = QStandardItem(QIcon(r"F:\学习\python\资源\图像文件\save.png"), 'save.png') ICon4 = QStandardItem(QIcon(r"F:\学习\python\资源\图像文件\search.png"), 'search.png') ICon5 = QStandardItem(QIcon(r"F:\学习\python\资源\图像文件\stop.gif"), 'stop.gif') self.model.appendRow(ICon1) self.model.appendRow(ICon2) self.model.appendRow(ICon3) self.model.appendRow(ICon4) self.model.appendRow(ICon5) self.listView.setModel(self.model)
运行后的界面初始化截图以下:
使用项的setData( QtCore.QVariant(icon), Qt.DecorationRole)方法,对应数据角色使用 Qt.DecorationRole。示例代码:
def initIconModel(self): self.model = QStandardItemModel() ICon1 = QStandardItem('add.png') ICon1.setData(QtCore.QVariant(QIcon(r"F:\学习\python\资源\图像文件\add.png")),Qt.DecorationRole) ICon2 = QStandardItem('save.png') ICon2.setData(QtCore.QVariant(QIcon(r"F:\学习\python\资源\图像文件\save.png") ),Qt.DecorationRole) self.model.appendRow(ICon1) self.model.appendRow(ICon2) self.listView.setModel(self.model)
运行截图:
其实还有个相似的方法,就是使用model的setData( QModelIndex,QtCore.QVariant(icon), Qt.DecorationRole)方法,当选择操做时要更改图标文件可使用这种方法。只要在方法中获取到modelIndex就能够调用该方法。
在QListView视图中数据若是发生变化,能够经过QStandardItemModel的信号itemChanged链接一个自定义槽函数来获取变更的数据。
一、定义一个槽函数itemChanged
def itemChanged(self,item): print(f"itemChanged,row={item.row()},column={item.column()}")
二、在构造方法中创建信号和槽的链接
self.model.itemChanged[QStandardItem ].connect(self.itemChanged)
这样只要触发了项的编辑就会发出该信号从而知道变更的数据项。
本节经过案例详细介绍了QListView/Model编程的几个要点,包括QListView与不一样model的配合步骤、多列Model中数据展现列的控制、给展现数据加上图标、获取变动数据项的方法等内容。
另外老猿关于PyQt的付费专栏《使用PyQt开发图形界面Python应用》只须要9.9元,该部分与第十五章的内容基本对应,但一样内容在付费专栏上整体来讲更详细、案例更多。本节内容在付费专栏的《第十八章、QListView/Model开发》。若是有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。
最后感谢各位支持,大家的支持是我持续学习和更新的动力!