Read-Only QAbstractTableModel
Subclass
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import sys
import csv
from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt
from PySide6.QtWidgets import (QApplication,
QWidget, QTableView, QVBoxLayout)
from PySide6.QtTest import QAbstractItemModelTester
# 1. Create a QAbstractTableModel subclass.
# We read the data from a csv file using Python's csv.reader
# Each row in a reader object is a list making self.csv_data
# a two-dimensional list suitable for use
# with QAbstractTableModel.
class CsvModel(QAbstractTableModel):
def __init__(self, source, parent=None):
super().__init__(parent)
self.csv_data = []
with open(source) as csv_file:
reader = csv.reader(csv_file)
self.header = next(reader)
for row in reader:
self.csv_data.append(row)
# 2. Implement the rowCount() and columnCount() methods
def rowCount(self, parent=QModelIndex()):
return len(self.csv_data)
def columnCount(self, parent=QModelIndex()):
return 4
# 3. Implement the data() method
def data(self, index, role):
if role == Qt.ItemDataRole.DisplayRole:
return self.csv_data[index.row()][index.column()]
# QTableView can have a header
# but implementing headerData() is still optional.
def headerData(self, section, orientation, role):
if orientation == Qt.Orientation.Horizontal:
if role == Qt.ItemDataRole.DisplayRole:
return self.header[section]
class Window(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout()
self.setLayout(layout)
# 4. Use the model:
# Create a model instance, create a view instance
# and and use view.setModel() to connect them.
model = CsvModel('data.csv')
QAbstractItemModelTester(model)
view = QTableView()
view.setModel(model)
view.resizeColumnsToContents()
layout.addWidget(view)
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = Window()
main_window.show()
sys.exit(app.exec())
QAbstractTableModel
lets you make your two-dimensional data available to Qt views. Just as with QAbstractListModel
it can be read-only, editable and resizable, depending on the base class methods you choose to implement. To use a read-only QAbstractTableMOdel
object in your program
-
Create a subclass of
QAbstractTableModel
namedCsvModel
and make external data available to it. We read the data from the same csv file as in theQAbstractListModel
example,data.csv
using Python’s csv reader and store it in a member variable namedself.csv_data
.csv_data
is a list and csv reader’s rows are also lists which effectively makescsv_data
a two-dimensional list suitable for use withQAbstractTableModel
subclasses -
Implement the
rowCount()
and thecolumnCount()
methods.rowCount()
is the length of theself.csv_data
list and never changes since the model is read-only.columnCount()
is hard-coded to return 4, the number of columns in the csv file. -
Implement the
data()
method.data()
expects two arguments:index
, aQModelIndex
instance androle
, a member of theDisplayRole
enumeration. In thedata()
body we check ifrole
is equal toDisplayRole
and if it is we return the data that the index points to. Note that we need to use bothindex.row()
andindex.column()
as the data has two dimensions. With this you have a functionalQAbstracttableModel
subclass. -
In your main class (
Window
), create aCsvModel
object, create aQTableView
object and set its model usingQTableView()setModel()
QAbstractTableModel
subclasses are commonly used with QTableView
but not necessarily so. QTableView
is able to display table headers using the header data you provide to it in the model headerData()
method but implementing headerData()
is still not mandatory.