PyQt5 QAbstractTableModel,QStringListModel使用方法

向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
 


這種方法有什麼好的呢?我認爲這樣可以實現動態綁定,我們通過修改列表中的數據,就可以該表視圖中的數據.優勢是不言而喻的.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....)
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章