Python+PySide6之模型/视图/委托框架QListView案例实践

这篇具有很好参考价值的文章主要介绍了Python+PySide6之模型/视图/委托框架QListView案例实践。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Qt中的模型/视图/委托框架是一种数据与可视化相互分离的技术,起源于Smalltalk的设计模式——Mode/View/Controller(MVC,模型/视图/控制器),通常在构建用户界面时使用。

MVC是由3部分组成。Model是应用程序对象,View是它的界面展示,Controller定义了界面对用户输入的反应方式。

Qt提供的技术方法和MVC稍有不同,称为Model/View/Delegate(模型/视图/委托),可以提供与MVC相同的全部功能,如下图,MVC中的控制器的部分功能既可以通过委托实现,也可以通过模型实现。

pyside6 tableview model,python,pyqt,学习,笔记

一般来说,模型从数据源中读/写数据,视图从模型的索引中获取需要呈现的数据,并通过委托绘制。对于用户的编辑操作,视图会要求委托提供一个编辑器,并把编辑后的结果传递给模型。模型、视图和委托使用信号/槽机制相互通信。

  • 来自模型的信号将数据源的变更信息通知视图。
  • 来自视图的信号提供用户与当前项目的交互信息。
  • 来自委托的信号在编辑的时候告诉模型和视图编辑器的状态。

一、关于模型(Model):

模型中数据存储的基本单元是item,每个item都对应唯一的索引值(QModelIndex),每个索引值都有3个属性:行、列、父对象。

对于一维模型,如列表(List),只会用到行

对于二维模型,如表格(Table),会用到行和列

对于三维模型,如树(Tree),会用到行、列、父对象。

所有模型都基于QAbstractItemModel类,它定义了一个接口,视图和委托使用该接口访问数据。通过该接口数据不一定要存储在模型中,可以保持在由单独的类、文件、数据库或者默写其它应用程序组件提供的数据结构或者存储库中。

QAbstactItemModel是处理列表、表格、树的基类,在此基础上,QAbstactListModel和QAbstractTableMode提供了处理列表和表格的更好选择,因为它们提供了一些常用的方法。需要注意的是,这3个Model都是抽象模型,必须子类化并且要重新实现部分方法才能使用。如果不想这么麻烦,Qt也提供了一些便准的现有模型,可以直接实例化处理数据。

  • QStringListModel,用于存储QString项的简单列表,一般和QListView或者QComboBox一起使用。
  • QStandardItemModel,可以管理更复杂的项目树结构,可以用于表示列表、表格、树视图所需要的各种不同的数据结构,该模型还包含了数据项,每个项可以包含任意数据。QStandardItemModel可以与QListView,QTableView和QTreeView一起使用。
  • QFileSystemModel是一个用于维护有关目录内容的信息的模型,它本身不保存任何数据,只是表示本地文件系统上的文件和目录。QFileSystemModel可以与QListView、QTableView、QTreeView一起使用。
  • QSqlQueryModel、QSqlTableModel、QSqlRelationalTableModel用于使用模型/视图约定访问数据库,一般和QTableView一起使用。

模型角色:

模型中的项目可以为其它组建执行各种角色,允许为不同情况提供不同类型的数据,比如使用setText(),setIcon(),setForeground()等函数可以设置不同的角色。例如,在视图中正常显示字符串需要设置Qt.DisplayRole角色,这一般是项目的默认角色;为项目添加ToolTip提示功能,需要设置Qt.ToolTipRole角色;设置项目item的文本颜色,需要设置Qt.ForegroundRole角色。

一个项目item可以包含多个不同角色的数据,也就是说拥有这些角色,标准角色由Qt.ItemDataRole定义。

模型通过索引(QModelIndex)定位角色,使用setData()函数可以设置角色,使用data()函数可以获取角色。

有些模型(如QStringListMode)只支持字符串,不支持颜色、图片等角色;有些模型(如QStandardItemMode)支持字符串、颜色、图片等多种角色。

二、关于视图(View):

视图从模型中获取数据并在界面上呈现。QListWidget/QTableWidget/QTreeWidget是分别继承QListView/QTableView/QTreeView类,包含了默认的模型,使用简单一些,但是QListView/QTableView/QTreeView类更加灵活,配合不同模型(Model)可以处理更复杂的数据处理,比如数据的筛选、过滤、复杂计算、及时更新等。

  • QListView:在列表中显示模型的数据,一般和QStringListModel一起使用,也可以使用QStandardItemModel。使用QFileSystemModel可以显示本地文件目录。
  • QTableView:在表格中显示模型的数据,一般和QStandardItemModel一起使用。如果要显示数据库数据,则可以使用QSqlQueryModel、QSqlTableModel、QSqlRelationalModel。使用QFileSystemModel可以显示文件目录。
  • QTreeView:在树中显示模型的数据,一般和QStandardItemModel一起使用,使用QFileSystemModel可以显示文件目录。

三、关于委托(Delegate):

Delegate(委托或代理)的作用包括以下两个方面:

绘制视图中来自模型的数据,委托会参考项目的角色和数据进行绘制,不同的角色和数据有不同的绘制效果(比如字符串颜色,字体,背景色,图标等)。

在视图与模型之间交互操作时提供临时编辑组件的功能,该编辑器位于视图的顶层。

QAbstractItemDelegate是委托的抽象基类,它的子类QStyledItemDelegate是所有Qt项目视图的默认委托,并在创建视图时自动安装。QStyledItemDelegate是QListView、QTableView、QTreeView的默认委托,如果要编辑QTableView,那么其默认委托(QStyledItemDelegate)会提供QLineEdit作为编辑器;对于子类QListWidget/QTableWidget/QTreeWidget也一样。如果要使用其他编辑器,比如vQTableView使用QSpinBox作为委托编辑器,就需要通过自定义委托实现。

四、QListView应用案例:

QListView是Qt中用来存储列表的纯视图类。QListView是基于Qt模型/视图/委托架构提供更灵活的方法,一般与QStringListModel绑定管理数据。

1、绑定模型和初始化数据

QListView需要绑定模型,一般绑定QStringListModel模型。QStringListModel是一个可编辑模型,,提供了可编辑模型的所有标准功能,可用于在视图小部件中显示多个字符串的简单情况。

模型既可以在实例化时传递字符串列表来初始化数据,也可以使用setStringList()函数设置字符串,视图绑定模型使用setModel()函数。

实例化时传递字符串列表初始化数据示例:

# 使用for循环表达式,创建一个字符串列表
model = QStringListModel(['行'+str(i) for i in range(6)])

使用setStringList()函数初始化数据示例:

model = QStringListMode()
model.setStringList(['行'+str(i) for i in range(6)])

视图绑定模型示例:

# 实例化一个QListView列表视图对象
listView = QListView()
# 实例化QStringListModel模型
model = QStringListModel(['row'+str(i) for i in range(6)])
# 列表视图绑定模型
listView.setModel(model)

2、增、删、改、查、移、选

关于数据的操作要通过模型来完成,下面介绍的是QStringListModel的相关函数。

使用index()函数可以获取item对应的模型索引;使用flag()函数可以获取item的flag信息,该信息决定了item是否可以被选中、编辑及交互等。如果item的flag为Qt.NoItemFlags,那么该item将无法被选择、编辑、拖动等。

data()将用于获取项目数据,setData()函数,insertRow()和insertRows()用于插入行,removeRow()和removeRows()用于删除行,rowCount()用于获取列表的长度,stringList()函数用于获取字符串列表的内容,moveRow()函数用于移动行。

关于添加行(没有提供addRow()函数),通过使用insertRow()函数,在模型的末尾(通过获取模型的行数,得到索引值)来添加一行。

# 获取模型的行数
num = model.rowCount()
# 因为索引从0开始,使用模型的行数num(整数),实现在模型数据项的末尾添加1行
model.insertRow(num)

# 给模型添加内容,setData()的一个参数类型是模型索引,不是整数类型
index = model.index(row)
text ='给模型添加的字符串数据'
# 给添加的行,设置数据,需要该行的索引
model.setData(index,text)

3、一个综合案例代码

import os
import sys
from PySide6.QtWidgets import *
from PySide6.QtGui import *
from PySide6.QtCore import *

class QListViewDemo(QWidget):
    addCount = 0
    insertCount = 0

    def __init__(self, parent=None) :
        super(QListViewDemo,self).__init__(parent)
        self.setWindowTitle("QListView案例")

        self.text = QPlainTextEdit("用来显示QListView相关信息:")
        self.listView = QListView()
        # 定义一个QStringListMoel模型,可以先创建模型,然后定义数据;也可以直接创建模式时创建数据
        # self.model = QStringListModel() 
        # self.model.setStringList(['行'+str(i) for i in range(6)])
        self.model = QStringListModel(['行' + str(i) for i in range(6)])
        
        # 把视图(listView对象)和模式进行关联
        self.listView.setModel(self.model)

        # 定义第二个视图对象(listView),依然关联上面的模式。
        # 在视图1中更改模式,会发现在视图2中会发生同样的变化。
        self.listView2 = QListView()
        self.listView2.setModel(self.model)
        # 设置列表视图2的最大高度100像素
        self.listView2.setMaximumHeight(180)

        # 定义一组按钮
        self.buttonAdd = QPushButton('增加')
        self.buttonDelete = QPushButton('删除')
        self.buttonUp = QPushButton('上移')
        self.buttonDown = QPushButton('下移')
        self.buttonInsert = QPushButton('插入')

        # 定义上面5个按钮的单击信号槽函数
        self.buttonAdd.clicked.connect(self.onAdd)
        self.buttonInsert.clicked.connect(self.onInsert)
        self.buttonUp.clicked.connect(self.onUp)
        self.buttonDown.clicked.connect(self.onDown)
        self.buttonDelete.clicked.connect(self.onDelete)

        # 定义一个水平布局管理器,把上面5个按钮对象加入,进行水平布局
        layoutH = QHBoxLayout()
        layoutH.addWidget(self.buttonAdd)
        layoutH.addWidget(self.buttonInsert)
        layoutH.addWidget(self.buttonUp)
        layoutH.addWidget(self.buttonDown)
        layoutH.addWidget(self.buttonDelete)

        # 定义一组按钮
        self.buttonSelectAll = QPushButton('全选')
        self.buttonClear = QPushButton('清除选择')
        self.buttonSelectOutput = QPushButton('输出选择')

        # 定义上面3个按钮的单击信号槽函数
        #

        # 定义一个水平布局管理器,加入上面3个按钮,进行水平布局
        layoutH2 = QHBoxLayout()
        layoutH2.addWidget(self.buttonSelectAll)
        layoutH2.addWidget(self.buttonClear)
        layoutH2.addWidget(self.buttonSelectOutput)

        # 创建一个垂直布局管理器,作为主窗口上的主布局管理器
        layout = QVBoxLayout()
        layout.addWidget(self.listView)
        layout.addLayout(layoutH)
        layout.addLayout(layoutH2)
        layout.addWidget(self.text)
        layout.addWidget(self.listView2)

        # 把垂直布局管理器添加到主窗口
        self.setLayout(layout)

    def onAdd(self):
        self.addCount += 1
        # 新增项目的文本字符串
        text = f'新增--{self.addCount}'
        # 获取模型的行数
        num = self.model.rowCount()
        # 模型中插入一行,在模型的末尾(相当于追加)
        self.model.insertRow(num)
        # 获取模型的最后一行的索引
        index = self.model.index(num,0)
        # 因为两个视图都连接了上面一个模型,所以,视图中的数据都会更新
        # 注意:模型的行数与索引值,是不同的类型(对象),一个是<class 'int'> ,一个是<class 'PySide6.QtCore.QModelIndex'>
        self.model.setData(index,text)

        # 在文本框中显示一行内容:在模型中添加了一行数据
        self.text.appendPlainText(f'新增item:{text}')

    def onInsert(self):
        self.insertCount += 1
        # 获取当前行的索引对象
        index =self.listView.currentIndex()
        row = index.row()
        text = f'插入--{self.insertCount}'
        # 插入一个空白行,后面
        self.model.insertRow(row)
        # index对象是执行insertRow()前获取的索引,下面setData()函数,
        self.model.setData(index,text)

        #
        self.text.appendPlainText(f'行:{row},新增了item:{text}')

    def onUp(self):
        index = self.listView.currentIndex()
        row = index.row()
        if row > 0:  # 判断不是第一行(索引值为0)
            self.model.moveRow(QModelIndex(),row,QModelIndex(),row -1)

    def onDown(self):
        index = self.listView.currentIndex()
        row = index.row()
        if row <= self.model.rowCount() -1:
            self.model.moveRow(QModelIndex(),row+1,QModelIndex(),row)

    def onDelete(self):
        '''
        QListView对象总有一个currentIndex(),如果实例化的QListView对象的项目为空,
        row = index.row() # 返回为-1
        text = self.model.data(index) # 返回为None
        '''
        index = self.listView.currentIndex()
        text = self.model.data(index)
        row = index.row()
        if row >= 0 :
            self.model.removeRow(row)
            self.text.appendPlainText(f'行:{row},删除item{text}')


if __name__ == "__main__":

    app = QApplication(sys.argv)
    demo = QListViewDemo()
    demo.show()
    sys.exit(app.exec())

代码在deepin20系统下运行界面如下:

pyside6 tableview model,python,pyqt,学习,笔记

上面代码案例创建了2个QListView,绑定了同一个QStringListModel模型实例,通过几个按钮的单击信号与槽函数,实现了增加行、插入行、删除行、上移/下移行,两个视图数据是同步变化的,而且保持一致,依次来说明模型/视图框架的优越性,只须维护一套数据,绑定的所有视图呈现的数据将保持一致。文章来源地址https://www.toymoban.com/news/detail-831817.html

到了这里,关于Python+PySide6之模型/视图/委托框架QListView案例实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python项目——搞怪小程序(PySide6+Pyinstaller)

    1、介绍 使用python编写一个小程序,回答你是猪吗。 点击“是”提交,弹窗并退出。 点击“不是”提交,等待5秒,重新选择。 并且隐藏了关闭按钮。 2、实现 新建一个项目。 2.1、设计UI 使用Qt designer设计一个UI界面,保存ui文件,再转换为py文件并保存到项目目录中,供后续

    2024年01月22日
    浏览(45)
  • 基于YOLOV8模型的西红柿目标检测系统(PyTorch+Pyside6+YOLOv8模型)

    摘要:基于YOLOV8模型的西红柿目标检测系统可用于日常生活中检测与定位西红柿目标,利用深度学习算法可实现图片、视频、摄像头等方式的目标检测,另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检测算法训练数据集,使用Pysdie6库来搭

    2024年02月11日
    浏览(47)
  • 基于YOLOv8模型的深海鱼目标检测系统(PyTorch+Pyside6+YOLOv8模型)

    摘要:基于YOLOv8模型和BDD数据集的自动驾驶目标检测系统可用于日常生活与海洋中检测与定位深海鱼目标,利用深度学习算法可实现图片、视频、摄像头等方式的目标检测,另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检测算法训练数据

    2024年02月07日
    浏览(43)
  • 基于深度学习的CCPD车牌检测系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于CCPD数据集的高精度车牌检测系统可用于日常生活中检测与定位车牌目标,利用深度学习算法可实现图片、视频、摄像头等方式的车牌目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数据集,使用Pysdie6库来搭建

    2024年02月14日
    浏览(63)
  • Python项目——久坐提醒定时器(PySide6)编写

    1、介绍 使用Python编写一个久坐提醒软件。 功能: 设置工作时间。 设置休息时间。 选择休息时是否播放音乐。 休息时,软件置顶,且不能关闭。 2、工具 语言:python3.11 UI设计工具:Qt designer 编译器:PyCharm 包:pygame、PySide6 3、代码 新建一个项目,准备好音乐。 使用Qt des

    2024年01月19日
    浏览(49)
  • 基于YOLOv8模型的五类动物目标检测系统(PyTorch+Pyside6+YOLOv8模型)

    摘要:基于YOLOv8模型的五类动物目标检测系统可用于日常生活中检测与定位动物目标(狼、鹿、猪、兔和浣熊),利用深度学习算法可实现图片、视频、摄像头等方式的目标检测,另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检测算法训

    2024年02月12日
    浏览(43)
  • 基于YOLOV8模型的农作机器和行人目标检测系统(PyTorch+Pyside6+YOLOv8模型)

    摘要:基于YOLOV8模型的农作机器和行人目标检测系统可用于日常生活中检测与定位农作机和行人目标,利用深度学习算法可实现图片、视频、摄像头等方式的目标检测,另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检测算法训练数据集,

    2024年02月10日
    浏览(57)
  • 基于深度学习的高精度动物检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度动物检测识别系统可用于日常生活中或野外来检测与定位动物目标(狼、鹿、猪、兔和浣熊),利用深度学习算法可实现图片、视频、摄像头等方式的动物(狼、鹿、猪、兔和浣熊)目标检测识别,另外支持结果可视化与图片或视频检测结果的导

    2024年02月08日
    浏览(84)
  • 基于深度学习的高精度山羊检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度山羊检测识别系统可用于日常生活中或野外来检测与定位山羊目标,利用深度学习算法可实现图片、视频、摄像头等方式的山羊目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数据集,使用

    2024年02月07日
    浏览(62)
  • 基于深度学习的高精度水果检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度水果(苹果、香蕉、葡萄、橘子、菠萝和西瓜)检测识别系统可用于日常生活中或野外来检测与定位水果目标,利用深度学习算法可实现图片、视频、摄像头等方式的水果目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统

    2024年02月11日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包