PyQt5 QAbstractTableModel,QStringListModel使用方法

最新项目需要在PyQt中使用表格,列表等样式.一开始我的写法很简单,在Qt-designer中拖了QListWidget与QTableWidget.

向tableWdiget动态添加一行采用如下代码

    def _insert_to_table(self, tableWidget):
        '''将数据插入到表格中,self.table_data保存了一行所有数据'''
        tableWidget.insertRow(tableWidget.rowCount())
        for column in range(tableWidget.columnCount()):
            # print(self.table_data[column])
            item = QTableWidgetItem(str(self.table_data[column]))
            tableWidget.setItem(tableWidget.rowCount() - 1, column, item)

向listWidget动态添加一行采用如下代码

self.listWidget.addItem(name)

但这样很恶心,动态扩展性很差.网上对PyQt中QAbstractTableModel/QStringListModel介绍的很少,下面介绍一种符合Model/view设计模式的方法.当然仅仅贴出一段例子,具体细节要是要去参考官方文档.

dialog.py

# @Author  : 张帆
# @Site    : 
# @File    : teamleadersdialog.py
# @Software: PyCharm
import sys

from PyQt5.QtCore import QStringListModel
from PyQt5.QtWidgets import QDialog, QListView, QAbstractItemView, QDialogButtonBox, QVBoxLayout, QTableView, \
    QApplication

from learnMVC.currencymodel import CurrencyModel


class TeamLeadersDialog(QDialog):
    def __init__(self, leaders):
        super(TeamLeadersDialog, self).__init__()

        self.model = QStringListModel(self)
        self.model.setStringList(leaders)

        self.listView = QListView()
        self.listView.setModel(self.model)
        self.listView.setEditTriggers(QAbstractItemView.AnyKeyPressed | QAbstractItemView.DoubleClicked)
        self.buttonBox = QDialogButtonBox()
        self.insertButton = self.buttonBox.addButton("Insert", QDialogButtonBox.ActionRole)
        self.deleteButton = self.buttonBox.addButton("Delete", QDialogButtonBox.ActionRole)
        self.buttonBox.addButton(QDialogButtonBox.Ok)
        self.buttonBox.addButton(QDialogButtonBox.Cancel)
        self.insertButton.clicked.connect(self.insert)
        self.deleteButton.clicked.connect(self.del_)
        self.currencyMap = {
            "header": ["姓名", "性别", "年龄"],
            "data": [["张帆", "男", 24], ["张帆", "男", 24], ["张帆", "男", 24], ["张帆", "男", 24], ["张帆", "男", 24],
                     ["张帆", "男", 24]]
        }
        self.currencyModel = CurrencyModel(self.currencyMap.get('data'),self.currencyMap.get('header'))
        self.tableView = QTableView()
        self.tableView.setModel(self.currencyModel)
        self.tableView.setAlternatingRowColors(True)
        self.tableView.setWindowTitle("Currencies")
        self.tableView.show()
        self.mainLayout = QVBoxLayout()
        self.mainLayout.addWidget(self.listView)
        self.mainLayout.addWidget(self.buttonBox)
        self.mainLayout.addWidget(self.tableView)
        self.setLayout(self.mainLayout)
        self.setWindowTitle("Team leaders")
        self.count = 0

    def leaders(self):
        return self.model.stringList()

    def insert(self):
        row = self.model.rowCount()
        print(row)
        self.model.insertRow(row)
        index = self.model.index(row)
        self.model.setData(index,"123")
        currencyMap = {
            "header": ["姓名", "性别", "年龄"],
            "data": [["张帆", "男", 242], ["张帆", "男", 24], ["张帆", "男", 24], ["张帆", "男", 24], ["张帆", "男", 24],
                     ["张帆", "男", 24],['sdaf','asdf','asdf']]
        }
        x = self.tableView.currentIndex()

        self.currencyModel.append_data(['zhangfan','nf',str(self.count)])
        self.count+=1
        print(self.currencyModel.data)



    def del_(self):
        self.model.removeRows(self.listView.currentIndex().row(), 1)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    leaders = ['1','2','3','4','5','6','6']
    teamLeadersDialog = TeamLeadersDialog(leaders)
    teamLeadersDialog.show()
    app.exec_()

currencymodel.py

# -*- coding: utf-8 -*-
# @Time    : 18-12-1 下午3:26
# @Author  : 张帆
# @Site    : 
# @File    : currencymodel.py
# @Software: PyCharm
from PyQt5.QtCore import QAbstractTableModel, QVariant, Qt


class CurrencyModel(QAbstractTableModel):
    def __init__(self,data:list,header):
        super(CurrencyModel, self).__init__()
        self.data = data
        self.header = header


    def append_data(self,x):
        self.data.append(x)
        self.layoutChanged.emit()

    def remove_row(self,row):
        self.data.pop(row)
        self.layoutChanged.emit()

    def rowCount(self, parent=None, *args, **kwargs):
        return len(self.data)

    def columnCount(self, parent=None, *args, **kwargs):
        if len(self.data) > 0:
            return len(self.data[0])
        return 0


    def get_data(self):
        return self
    # 返回一个项的任意角色的值,这个项被指定为QModelIndex
    def data(self, QModelIndex, role=None):
        if not QModelIndex.isValid():
            print("行或者列有问题")
            return QVariant()
        # if role == Qt.TextAlignmentRole:
        #     return int(Qt.AlignRight | Qt.AlignVCenter)
        # elif role == Qt.DisplayRole:
        #     row = QModelIndex.row()
        #     column = QModelIndex.column()
        #     return self.currencyMap.get('data')[row][column]
        # # print("查数据")
        # row = QModelIndex.row()
        # # print('role:',role)
        # if role is None:
        #     return self.currencyMap.get('data')[row]
        elif role != Qt.DisplayRole:
            return QVariant()
        return QVariant(self.data[QModelIndex.row()][QModelIndex.column()])


    def headerData(self, p_int, Qt_Orientation, role=None):
        # if role != Qt.DisplayRole:
        #     return QVariant()
        # else:
        #     if Qt_Orientation == Qt.Horizontal:
        #         if len(self.currencyMap.get('header')) > p_int:
        #             return self.currencyMap.get('header')[p_int]
        if Qt_Orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return QVariant(self.header[p_int])
        return QVariant

PyQt5 QAbstractTableModel,QStringListModel使用方法_第1张图片

这种方法有什么好的呢?我认为这样可以实现动态绑定,我们通过修改列表中的数据,就可以该表视图中的数据.优势是不言而喻的.QStringListModel就不在解释了,挺简单的.下面对使用到currencymodel.py 简单的解释以下,我自己也不太明白,如有问题,请指出.

 

1.首先该类继承了QAbstractTableModel,就必须要实现rowCount(),columnCount(),data(),headerData()

2.初始化:

    1.指定表格数据结构,我设计的结构为 [['xxx','xxx','xxx'],['ttt','ttt','ttt'],...,]

    2.指定表头数据结构,我设计的结构为['xxx','xxx','xxx']

2.rowCount() 要返回该表格的行数

3.columnCount() 返回该表格的列数

4.data()    此方法我也不太了解,但调试时发现,他会经常逐表格调用,QModelIndex的值会根据行数列数的值,遍历每一个单元格

所以此处根据QModelIndex返回每一个单元格的值

5.headerData 与4相似,会根据列数自动调用

6.append_data  如果我们要动态的增加一行,只需要向self.data列表增加一行,之后调用self.layoutChanged.emit()即可

7.remove_data 同上,如果要动态删除一行,只需要将self.data指定行删除,之后调用self.layoutChanged.emit()即可.

至此,我们就可以实现数据与视图绑定,进一步实现set_data 应该可以实现双向绑定(vue....)

网上关于pyqt的资料真的很少,这点东西,都是花了1天的时间,看了不少C++代码才写出来的,感觉qt相对于前端氛围还是太差了,是不是要被淘汰呢...总而言之,希望这些对大家有所帮助.

你可能感兴趣的:(PyQt5 QAbstractTableModel,QStringListModel使用方法)