向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....)