PySide6学习笔记之模型/视图框架使用案例

在图形界面应用中,经常需要显示二维数据信息,如果数据仅仅显示且不频繁变更刷新,使用QTableWidget是更好的选择,QTableWidget内置了标准的数据模型,继承QTableView类。如果需要频繁刷新数据,比如查询和显示数据库相关表的数据,使用QTableView+QSqlQueryModel是比较好的选择。

下面是一个实例代码,程序运行的界面如下:

在Python程序代码所在文件夹中有一个“db”文件夹,db文件夹中有一个Sqlite3数据库文件“database.db”,有一个数据库表“student”,信息如下:

使用Python查询student表数据,并进行分页显示,每页10条记录,详细代码如下:

#! /home/liuyf/miniconda3/envs/py312
# -*- coding: utf-8 -*-
'''
@File    :   PySide6_QSqlQueryModel.py
@Time    :   2023/11/30 01:39:05
@Author  :   诚外无物 
@Version :   1.0
@Desc    :   使用模型/视图框架,QTableView控件绑定QSqlQueryModel模型,查询及分页显示数据库数据信息。
'''

import os 
import sys
from typing import Optional
import PySide6.QtCore
from PySide6.QtGui import *
from PySide6.QtCore import *
from PySide6.QtWidgets import *
from PySide6.QtSql import QSqlDatabase,QSqlQuery,QSqlQueryModel
import PySide6.QtWidgets

os.chdir(os.path.dirname(__file__))

ID,NAME,SUBJECT,SEX,AGE,SCODE,DESCRIBE = range(7)

class SqlQueryModelDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('查询数据库学生信息--分页查询案例')
        self.setWindowIcon(QIcon('./images/cartoon1.ico'))
        self.resize(550,400)

        # 创建窗口控件及布局
        self.createWindow()

        # 设置表格
        self.setTableView()

    # 创建窗口控件及布局函数
    def createWindow(self):
        # 操作布局: 一组控件进行水平布局
        operatorLayout = QHBoxLayout()
        # 创建一组按钮
        self.prevButton = QPushButton('前一页')
        self.nextButton = QPushButton('后一页')
        self.firstButton = QPushButton('第一页')
        self.lastButton = QPushButton('最后一页')
        #switchPageLabel = QLabel('转到第')
        # 创建单行文本输入框对象,并设置输入为整数,及宽度
        self.switchPageLineEdit = QLineEdit()        
        self.switchPageLineEdit.setValidator(QIntValidator(self))
        self.switchPageLineEdit.setFixedWidth(40)
        #pageLabel = QLabel('页')
        self.switchPageButton = QPushButton('Go')

        # 信号与槽函数
        self.nextButton.clicked.connect(self.onNextButtonClick)
        self.firstButton.clicked.connect(self.onFirstButtonClick)
        self.prevButton.clicked.connect(self.onPrevButtonClick)
        self.lastButton.clicked.connect(self.onLastButtonClick)
        self.switchPageButton.clicked.connect(self.onSwitchPageButtonClick)

        # 把上面控件添加到水平布局对象中
        operatorLayout.addWidget(self.firstButton)
        operatorLayout.addWidget(self.prevButton)
        operatorLayout.addWidget(self.nextButton)
        operatorLayout.addWidget(self.lastButton)
        operatorLayout.addWidget(QLabel('转到第'))
        operatorLayout.addWidget(self.switchPageLineEdit)
        operatorLayout.addWidget(QLabel('页'))
        operatorLayout.addWidget(self.switchPageButton)
        # 添加一个弹簧控件,窗口拉伸,前面的对象均大小不变
        operatorLayout.addWidget(QSplitter())

        # 状态布局 : 创建及添加3个状态信息Label对象,显示信息
        statusLayout = QHBoxLayout()
        self.totalPageLabel = QLabel()
        self.totalPageLabel.setFixedWidth(70)
        self.currentPageLabel = QLabel()
        self.currentPageLabel.setFixedWidth(70)

        self.totalRecordLabel = QLabel()
        self.totalRecordLabel.setFixedWidth(70)

        statusLayout.addWidget(self.totalPageLabel)
        statusLayout.addWidget(self.currentPageLabel)
        statusLayout.addWidget(QSplitter())
        statusLayout.addWidget(self.totalRecordLabel)

        # 设置表格属性
        self.tableView = QTableView()
        # 设置表格对象最后一列可扩展,窗口拉伸,则填满控件
        self.tableView.horizontalHeader().setStretchLastSection(True) 
        # 设置表格对象的列宽度,根据内容自动调整
        self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        
        # 创建界面
        main_layout = QVBoxLayout()
        main_layout.addLayout(operatorLayout)
        main_layout.addWidget(self.tableView)
        main_layout.addLayout(statusLayout)
        self.setLayout(main_layout)

    # 设置表格
    def setTableView(self):
        
        # 声明查询模型
        self.queryModel = QSqlQueryModel(self)

        # 设置当前页
        self.currentPage = 1
        # 设置每页显示记录数
        self.pageRecordCount = 10
        # 获取的总记录数
        self.totalRecordCount = self.getTotalRecordCount()
        # 总页数:因为int()实现四舍五入,加上0.5,确保不少一行
        self.totalPage = int(self.totalRecordCount / self.pageRecordCount + 0.5)

        # 设置总页数文本
        self.totalPageLabel.setText('总共%d页' % self.totalPage)
        # 设置总记录数文本
        self.totalRecordLabel.setText('共%d条' % self.totalRecordCount)

        # 设置模型
        self.tableView.setModel(self.queryModel)

        # 显示首页数据
        self.recordQuery(0)
        # 刷新状态
        self.updateStatus()

        # 设置表头
        self.queryModel.setHeaderData(ID,Qt.Horizontal,'编号')
        self.queryModel.setHeaderData(NAME,Qt.Horizontal,'姓名')
        self.queryModel.setHeaderData(SUBJECT,Qt.Horizontal,'科目')
        self.queryModel.setHeaderData(SEX,Qt.Horizontal,'性别')
        self.queryModel.setHeaderData(AGE,Qt.Horizontal,'年龄')
        self.queryModel.setHeaderData(SCODE,Qt.Horizontal,'分数')
        self.queryModel.setHeaderData(DESCRIBE,Qt.Horizontal,'说明')

    # 得到记录数
    def getTotalRecordCount(self):
        self.queryModel.setQuery('select count(*) from student')
        rowCount = self.queryModel.record(0).value(0)
        return rowCount
      
    # 记录查询
    def recordQuery(self,limitIndex):
        szQuery = ('select * from student limit %d,%d' %(limitIndex,self.pageRecordCount))
        print(szQuery)
        self.queryModel.setQuery(szQuery)
    
    # 刷新状态
    def updateStatus(self):
        szCurrentText = '当前第%d页' % self.currentPage
        self.currentPageLabel.setText(szCurrentText)

        # 设置按钮是否可用
        if self.currentPage == 1:
            self.firstButton.setEnabled(False)
            self.prevButton.setEnabled(False)
            self.nextButton.setEnabled(True)
            self.lastButton.setEnabled(True)
        elif self.currentPage >= self.totalPage -1:
            self.firstButton.setEnabled(True)
            self.prevButton.setEnabled(True)
            self.nextButton.setEnabled(False)
            self.lastButton.setEnabled(False)
        else:
            self.firstButton.setEnabled(True)
            self.prevButton.setEnabled(True)
            self.nextButton.setEnabled(True)
            self.lastButton.setEnabled(True)

    # 响应第一页按钮槽函数
    def onFirstButtonClick(self):
        self.recordQuery(0)
        self.currentPage = 1
        self.updateStatus()

    # 响应前一页按钮槽函数
    def onPrevButtonClick(self):
        limitIndex = (self.currentPage -2) * self.pageRecordCount
        self.recordQuery(limitIndex)
        self.currentPage -= 1
        self.updateStatus()
    
        
    # 响应后一页按钮的槽函数
    def onNextButtonClick(self):
        limitIndex = self.currentPage * self.pageRecordCount
        self.recordQuery(limitIndex)
        self.currentPage += 1        
        # 更新状态栏信息
        self.updateStatus()
    
    # 响应后一页按钮槽函数
    def onLastButtonClick(self):
        limitIndex = (self.totalPage -1) * self.pageRecordCount
        self.recordQuery(limitIndex)
        self.currentPage = self.totalPage
        self.updateStatus()

    # 响应跳转按钮槽函数
    def onSwitchPageButtonClick(self):
        szText = self.switchPageLineEdit.text()
        # 判断是否为空
        if szText == '':
            QMessageBox.information(self,'提示','请输入要跳转的页面数字!')
            return
        
        # 得到跳转页面,判断是否为合理的页面
        pageIndex = int(szText)
        if pageIndex > self.totalPage or pageIndex < 1:
            QMessageBox.information(self,'提示','没有指定的页面,请输入合适的页数。')
            return

        # 得到查询起始行号
        limitIndex = (pageIndex - 1) * self.pageRecordCount

        # 记录查询
        self.recordQuery(limitIndex)
        # 设置当前页
        self.currentPage = pageIndex
        # 刷新状态栏提示
        self.updateStatus()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    db = QSqlDatabase.addDatabase('QSQLITE')
    db.setDatabaseName('./db/database.db')
    if db.open() is not True:
        QMessageBox.critical(None,'open error','数据库打开失败。')
        exit()
    
    demo = SqlQueryModelDemo()
    demo.show()
    sys.exit(app.exec())

以上代码学习《PySide6/PyQt6快速开发与实践》一书,逐行敲入书中代码,经验证无误,仅调整部分代码顺序。

在主窗口上创建QTableView控件,绑定了QSqlQueryModel对象,刷新数据其实,就仅仅是更改QSqlQueryModel实例对象的查询sql语句,定义了一个简单的函数,传入参数,使用QSqlQueryModel类的setQuery(sql语句)方法,即可更新QTableView实例对象的数据显示。

def recordQuery(self,limitIndex):
        szQuery = ('select * from student limit %d,%d' %(limitIndex,self.pageRecordCount))
        self.queryModel.setQuery(szQuery)

在主程序上鼠标单击查询按钮,主要就是调用上面的recordQuery()函数。QSqlQueryModel数据变化,QTableView显示数据即变化。

以上代码体现了Qt的模型/视图框架的灵活性。

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据您提供的引用内容,Pyside6是一个用于创建跨平台图形用户界面(GUI)应用程序的Python模块。它是Qt应用程序框架Python绑定库。在部署Pyside6模型方面,可以使用PyInstaller等工具来将Pyside6应用程序打包成可执行文件以供部署使用。PyInstaller是一个流行的Python程序打包工具,可以将Python应用程序和其依赖项打包成一个独立的可执行文件,以便在不同的操作系统上运行。 要部署Pyside6模型,您可以按照以下步骤进行操作: 1. 确保已经安装了Pyside6库和PyInstaller工具。 2. 在命令行中导航到您的Pyside6应用程序所在的目录。 3. 使用PyInstaller命令将应用程序打包成可执行文件。例如,可以运行以下命令:pyinstaller --onefile your_script.py 这将生成一个包含您的Pyside6应用程序的可执行文件。 4. 完成打包后,您可以将生成的可执行文件复制到目标计算机上,并可以在该计算机上运行您的Pyside6应用程序。 请注意,这只是一种常见的部署Pyside6模型的方法之一。根据您的具体需求和平台,可能会有其他不同的部署方法可供选择。建议查阅Pyside6和PyInstaller的官方文档以获取更多详细的部署指南和最佳实践。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [实战YOLOv5-入门篇笔记 YOLOv5 Pyside6可视化界面](https://blog.csdn.net/weixin_41987016/article/details/129870700)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [pyside6官方示例](https://download.csdn.net/download/studywj/85536892)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值