程序人生
PyQt5使用QtableView增删改查分页
作者:邵波涛    时间:2017-01-02 浏览量:448

使用PyQt5制作了一个简单的增删改查分页的示例,使用peewee操作数据库也非常便捷,实时改动实时刷新。

首先是GUI代码UI_example:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'D:\e6pyqt5\example.ui'
#
# Created by: PyQt5 UI code generator 5.7
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Exalmple(object):
    def setupUi(self, Exalmple):
        Exalmple.setObjectName("Exalmple")
        Exalmple.resize(314, 374)
        Exalmple.setSizeGripEnabled(True)
        self.label = QtWidgets.QLabel(Exalmple)
        self.label.setGeometry(QtCore.QRect(20, 250, 54, 12))
        self.label.setObjectName("label")
        self.aidtext = QtWidgets.QLineEdit(Exalmple)
        self.aidtext.setEnabled(False)
        self.aidtext.setGeometry(QtCore.QRect(90, 240, 113, 20))
        self.aidtext.setReadOnly(False)
        self.aidtext.setObjectName("aidtext")
        self.label_2 = QtWidgets.QLabel(Exalmple)
        self.label_2.setGeometry(QtCore.QRect(20, 280, 54, 12))
        self.label_2.setObjectName("label_2")
        self.titletext = QtWidgets.QLineEdit(Exalmple)
        self.titletext.setGeometry(QtCore.QRect(90, 270, 113, 20))
        self.titletext.setObjectName("titletext")
        self.add = QtWidgets.QPushButton(Exalmple)
        self.add.setGeometry(QtCore.QRect(20, 340, 51, 23))
        self.add.setObjectName("add")
        self.delp = QtWidgets.QPushButton(Exalmple)
        self.delp.setGeometry(QtCore.QRect(90, 340, 51, 23))
        self.delp.setObjectName("delp")
        self.mod = QtWidgets.QPushButton(Exalmple)
        self.mod.setGeometry(QtCore.QRect(160, 340, 51, 23))
        self.mod.setObjectName("mod")
        self.sea = QtWidgets.QPushButton(Exalmple)
        self.sea.setGeometry(QtCore.QRect(220, 340, 75, 23))
        self.sea.setObjectName("sea")
        self.pre = QtWidgets.QPushButton(Exalmple)
        self.pre.setGeometry(QtCore.QRect(220, 240, 75, 23))
        self.pre.setObjectName("pre")
        self.nex = QtWidgets.QPushButton(Exalmple)
        self.nex.setGeometry(QtCore.QRect(220, 270, 75, 23))
        self.nex.setObjectName("nex")
        self.stext = QtWidgets.QLineEdit(Exalmple)
        self.stext.setGeometry(QtCore.QRect(220, 300, 71, 20))
        self.stext.setObjectName("stext")
        self.lincid = QtWidgets.QLineEdit(Exalmple)
        self.lincid.setGeometry(QtCore.QRect(90, 300, 113, 20))
        self.lincid.setObjectName("lincid")
        self.label_3 = QtWidgets.QLabel(Exalmple)
        self.label_3.setGeometry(QtCore.QRect(20, 310, 54, 12))
        self.label_3.setObjectName("label_3")
        self.tableView = QtWidgets.QTableView(Exalmple)
        self.tableView.setGeometry(QtCore.QRect(10, 10, 291, 221))
        self.tableView.setObjectName("tableView")

        self.retranslateUi(Exalmple)
        QtCore.QMetaObject.connectSlotsByName(Exalmple)

    def retranslateUi(self, Exalmple):
        _translate = QtCore.QCoreApplication.translate
        Exalmple.setWindowTitle(_translate("Exalmple", "example"))
        self.label.setText(_translate("Exalmple", "编号"))
        self.label_2.setText(_translate("Exalmple", "标题"))
        self.add.setText(_translate("Exalmple", "增"))
        self.delp.setText(_translate("Exalmple", "删"))
        self.mod.setText(_translate("Exalmple", "改"))
        self.sea.setText(_translate("Exalmple", "查"))
        self.pre.setText(_translate("Exalmple", "上一页"))
        self.nex.setText(_translate("Exalmple", "下一页"))
        self.label_3.setText(_translate("Exalmple", "分类编号"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Exalmple = QtWidgets.QDialog()
    ui = Ui_Exalmple()
    ui.setupUi(Exalmple)
    Exalmple.show()
    sys.exit(app.exec_())

接下来需要先准备好数据库操作文件db

from peewee import *

database = MySQLDatabase(
    'db_test', **{'user': 'root', 'port': 3306, 'password': '', 'host': 'localhost'})


class UnknownField(object):

    def __init__(self, *_, **__): pass
class BaseModel(Model):

    class Meta:
        database = database
        
class TArticle(BaseModel):
    aid = PrimaryKeyField()
    cid = IntegerField()   
    title = CharField(index=True)
    class Meta:
        db_table = 't_article'

好了,接下来需要自定义一下tableview的model类DataModel

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from db import *
#转换数据库查询结果为列表
def QueryTolist(obs):
    data=[]
    for ob in obs:
        data.append(ob)
    return data
aid, title, cid = range(3)
class ArticleModel(QAbstractTableModel):   
    
    def __init__(self):
        super(ArticleModel, self).__init__()
        self.columns = [u'编号', u'标题',u'分类编号']
        self.TableData=TArticle.select()
        self.records = QueryTolist(self.TableData)     
    #根据条件筛查数据并通知model重新填充数据     
    def queryData(self,condition,value):
        if condition=='where':
            self.records=QueryTolist(self.TableData.where(value))
        elif condition=='limit':
            self.records=QueryTolist(self.TableData.limit(value))
        elif condition=='page':
            self.records=QueryTolist(self.TableData.paginate(value[0],value[1]))
        self.reflushData()
    #不知道是不是正统,总之只有该方法才能实时刷新数据
    def reflushData(self):
        self.endResetModel()
    def rowCount(self, parent=QModelIndex()):
        return len(self.records)

    def columnCount(self, parent=QModelIndex()):
        return len(self.columns)

    def data(self, index, role=Qt.DisplayRole):
        record = self.getRecord(index)
        if not record:
            return QVariant()
        column = index.column()
        if role == Qt.DisplayRole or role==Qt.EditRole:
            if column == title:
                return QVariant(str(record.title))
            elif column == aid:
                return QVariant(str(record.aid))            
            elif column == cid:
                return QVariant(str(record.cid))            
        elif role == Qt.TextColorRole:
            if column == aid:
                return QVariant(QColor(Qt.blue))
            elif column == title:
                return QVariant(QColor(Qt.red))     
        return QVariant()

    def headerData(self, col, orientation, role=Qt.DisplayRole):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return QVariant(self.columns[col])
        return QVariant()
    #flags与setData两个函数的实现可以让model可编辑,如果不需要就地编辑,可以不重载这两个函数
    def flags(self, index):
        flag=super(ArticleModel,self).flags(index)
        return flag | Qt.ItemIsEditable
    def setData(self, index, value, role=Qt.EditRole):
        if index.isValid() and 0 <= index.row() < len(self.records):
            record = self.records[index.row()]
            column = index.column()
            if column == aid:
                record.aid = value
            elif column == title:
                record.title = value
            elif column == cid:
                record.cid = value 
            TArticle.save(record)#通知数据库同时存储改变
            self.dataChanged.emit(index, index)
            return True
        return False   
    #返回model中的对象       
    def getRecord(self, index):
        if not index.isValid() or not (0 <= index.row() < len(self.records)):
            return None
        return self.records[index.row()]
    #重载insertrows,在position位置开始向下插入new_record对象,rows为插入的行数
    def insertRows(self, position, new_record, rows, parent=QModelIndex()):
        self.beginInsertRows(parent, position, position + rows - 1)
        for row in range(rows):
            self.records.insert(position + row, new_record)
        self.endInsertRows()
        return True

    def removeRows(self, position, rows, index=QModelIndex()):
        self.beginRemoveRows(index, position,
                             position + rows - 1)
        self.records[position].delete()
        self.records = self.records[:position] + \
            self.records[position + rows:]
        self.endRemoveRows()
        return True    

    def getLastRecord(self):
        if len(self.records) > 0:
            return self.records[-1]
        return None

最后是GUI中所有对象槽函数的实现example

# -*- coding: utf-8 -*-

"""
Module implementing Exalmple.
"""
import sys
from PyQt5.QtCore import pyqtSlot,QModelIndex
from PyQt5.QtWidgets import QDialog,QApplication
from DataModel import *
from db import *
from Ui_example import Ui_Exalmple


class Exalmple(QDialog, Ui_Exalmple):
    """
    Class documentation goes here.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(Exalmple, self).__init__(parent)
        self.setupUi(self)
        Model = ArticleModel()
        self.Count=Model.rowCount()
        self.cpage=1
        self.pagesize=3
        Model.queryData('page', (self.cpage,self.pagesize))
        self.tableView.setModel(Model)
    def pagecount(self):
        if self.Count%self.pagesize==0:
            pagecount=int(self.Count/self.pagesize) 
        else:
            pagecount=int(self.Count/self.pagesize)+1
        return pagecount    
    @pyqtSlot(QModelIndex)
    def on_tableView_clicked(self, index):
        """
        Slot documentation goes here.
        
        @param index DESCRIPTION
        @type QModelIndex
        """
        # TODO: not implemented yet
        artobj=self.tableView.model().getRecord(index)
        self.aidtext.setText(str(artobj.aid))
        self.titletext.setText(artobj.title)
        self.lincid.setText(str(artobj.cid))
   
    @pyqtSlot()
    def on_add_clicked(self):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        row=self.tableView.model().rowCount()
        artobj=TArticle()
        artobj.title=self.titletext.text()
        artobj.cid=int(self.lincid.text())
        TArticle.save(artobj)        
        self.tableView.model().insertRows(row,artobj,1)
        self.Count+=1
        index = self.tableView.model().index(row, 0)
        self.tableView.setCurrentIndex(index)
        #self.tableView.edit(index)        
        self.tableView.model().reflushData()
    
    @pyqtSlot()
    def on_delp_clicked(self):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        index = self.tableView.currentIndex()
        if not index.isValid():
            return        
        if (QMessageBox.question(self, u'删除提示',u'删除当前记录吗?', QMessageBox.Yes|QMessageBox.No) == QMessageBox.No):
            return               
        self.tableView.model().getRecord(index).delete_instance()
        self.tableView.model().removeRows(index.row(),1)
        self.Count-=1
    
    @pyqtSlot()
    def on_mod_clicked(self):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        index = self.tableView.currentIndex()
        artobj=self.tableView.model().getRecord(self.tableView.currentIndex())
        artobj.title=self.titletext.text()
        artobj.cid=int(self.lincid.text())
        TArticle.save(artobj)         
        self.tableView.model().reflushData()
    @pyqtSlot()
    def on_sea_clicked(self):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        self.tableView.model().queryData('where',R('aid=%s', self.stext.text()))
    
    @pyqtSlot()
    def on_pre_clicked(self):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        if self.cpage==1:
            self.tableView.model().queryData('page',(1,self.pagesize))            
        else:
            self.cpage-=1
            self.tableView.model().queryData('page',(self.cpage,self.pagesize))
    
    @pyqtSlot()
    def on_nex_clicked(self):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        if self.cpage==self.pagecount(): 
            self.tableView.model().queryData('page',(self.pagecount(),self.pagesize))             
        else:
            self.cpage+=1            
            self.tableView.model().queryData('page',(self.cpage,self.pagesize))   
if __name__=='__main__':
    app=QApplication(sys.argv)
    ui=Exalmple()
    ui.show()
    sys.exit(app.exec_())


发言请留称呼=>
本文留言
共有 0 条留言
扫一扫,手机浏览网站
友情链接
申请链接