Reputation: 103
I’m working on a Python GUI application with PyQt5 which has a QTableView for showing data.
Here is the code:
import sys
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import Qt
class DataModel(QtCore.QAbstractTableModel):
def __init__(self):
super().__init__()
self.data = []
def data(self, index, role):
if role == Qt.DisplayRole:
return self.data[index.row()][index.column()]
def rowCount(self, index):
return len(self.data)
def columnCount(self, index):
return len(self.data[0])
class MainWindow(UI.UserInterface):
def __init__(self):
super().__init__()
self.model = DataModel()
self.load()
self.TableView.setModel(self.model)
self.TableView.resizeColumnsToContents()
self.TableView.horizontalHeader().setStretchLastSection(True)
def load(self):
try:
self.model.data = [(1, '2020-01-10 00:00:00', 'KANIA', 'HENRYK', 4219)]
except Exception:
pass
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
The class UI.UserInterface
is in separate module. It has the QWidgets of the interface and layout QWidgets. One of them is QTableView
.
I can't seem to find a way to set the header labels for the QTableView
.
I looked for different solutions (some of them below) but none of them worked:
https://doc.qt.io/qt-5/sql-presenting.html (this one is written in C++. I don't quite understand it)
Upvotes: 4
Views: 10154
Reputation:
Override headerData
method of QTableAbstractModel
to set Columns and Rows name
def headerData(self, section: int, orientation: PySide6.QtCore.Qt.Orientation, role: int = ...):
#for setting columns name
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return f"Column {section + 1}"
#for setting rows name
if orientation == Qt.Vertical and role == Qt.DisplayRole:
return f"Row {section + 1}"
import sys
import requests
import PySide6
from PySide6.QtWidgets import QTableView, QWidget, QApplication, QGridLayout, QHeaderView
from PySide6.QtCore import Qt, QAbstractTableModel
from PySide6.QtGui import QColor, QIcon, QPixmap
from datetime import datetime
class MagicIcon():
def __init__(self, link):
self.link = link
self.icon = QIcon()
try:
response = requests.get(self.link)
pixmap = QPixmap()
pixmap.loadFromData(response.content)
self.icon = QIcon(pixmap)
except:
pass
class TableModel(QAbstractTableModel):
def headerData(self, section: int, orientation: PySide6.QtCore.Qt.Orientation, role: int = ...):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
# return f"Column {section + 1}"
return self.columns[section]
if orientation == Qt.Vertical and role == Qt.DisplayRole:
return f"{section + 1}"
def __init__(self, _data):
self.columns = ["Account", "Investment", "KYC", "Investment Date"]
# super().__init__(self)
super(TableModel, self).__init__()
self._data = _data
self.calendarLink = "https://img.icons8.com/fluency/48/000000/windows-calendar.png"
self.dollarLink = "https://img.icons8.com/external-vitaliy-gorbachev-lineal-color-vitaly-gorbachev/40/000000/external-dollar-currency-vitaliy-gorbachev-lineal-color-vitaly-gorbachev-1.png"
self.analysis = "https://img.icons8.com/external-flatarticons-blue-flatarticons/65/000000/external-analysis-digital-marketing-flatarticons-blue-flatarticons-1.png"
self.bug = "https://img.icons8.com/offices/30/000000/bug.png"
self.account = "https://img.icons8.com/plumpy/24/000000/edit-administrator.png"
self.approvedLink = "https://img.icons8.com/external-bearicons-flat-bearicons/40/000000/external-approved-approved-and-rejected-bearicons-flat-bearicons-9.png"
self.rejectedLink = "https://img.icons8.com/external-bearicons-flat-bearicons/40/000000/external-rejected-approved-and-rejected-bearicons-flat-bearicons-11.png"
self.naLink = "https://img.icons8.com/color/48/000000/not-applicable.png"
self.calendarIcon = MagicIcon(self.calendarLink).icon
self.accountIcon = MagicIcon(self.account).icon
self.dollarIcon = MagicIcon(self.dollarLink).icon
self.approvedIcon = MagicIcon(self.approvedLink).icon
self.rejectedIcon = MagicIcon(self.rejectedLink).icon
self.naIcon = MagicIcon(self.naLink).icon
def data(self, index, role):
if role == Qt.DisplayRole:
value = self._data[index.row()][index.column()]
if isinstance(value, datetime):
return value.strftime("%Y-%m-%d")
if isinstance(value, float):
return f"{value:.2f}"
return value
if role == Qt.TextAlignmentRole:
return Qt.AlignHCenter + Qt.AlignVCenter
if role == Qt.BackgroundRole:
return QColor("#adcdff") if index.row() % 2 == 0 else QColor("#d8ffc2")
if role == Qt.DecorationRole:
value = self._data[index.row()][index.column()]
if value is None:
return self.naIcon
if isinstance(value, datetime):
return self.calendarIcon
if index.column() == 0:
return self.accountIcon
if index.column() == 1:
return self.dollarIcon
if index.column() == 2:
if value == True:
return self.approvedIcon
elif value == False:
return self.rejectedIcon
return self.naIcon
def rowCount(self, index):
return len(self._data)
def columnCount(self, index):
return len(self._data[0])
class MainWindow(QWidget):
def __init__(self):
# super().__init__()
super(MainWindow, self).__init__()
self.resizeEvent = self.onResize
self.table = QTableView()
self.setWindowIcon(MagicIcon(
"https://img.icons8.com/external-flatarticons-blue-flatarticons/65/000000/external-analysis-digital-marketing-flatarticons-blue-flatarticons-1.png"
).icon)
self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# self.table.setSizeAdjustPolicy(QHeaderView.AdjustIgnored)
# self.table.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
data = [
["Andrew Mike", 15.255, True, datetime(2022, 1, 5)],
["Eliza Petterson", 353.555, False, datetime(2020, 1, 5)],
["Joseph Samuel", 123, None, datetime(2020, 1, 15)],
["Nita Singh", 266, True, datetime(2022, 2, 7)],
["Rahul Chakrabarti", 102, True, datetime(2019, 10, 15)],
]
self.model = TableModel(data)
self.table.setModel(self.model)
self.header = self.table.horizontalHeader()
# self.header.setSectionResizeMode(0, QHeaderView.Stretch)
# self.header.setSectionResizeMode(1, QHeaderView.)
# self.header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
self.layout = QGridLayout()
self.layout.addWidget(self.table, 0, 0)
self.setLayout(self.layout)
def onResize(self, event):
# print('old', event.oldSize(), 'new', event.size())
# super(MainWindow, self).resizeEvent(event)
pass
if __name__ == "__main__":
app = QApplication(sys.argv)
wid = MainWindow()
wid.show()
sys.exit(app.exec())
Upvotes: 3
Reputation: 177
here is an exemple using a QtableView and a set headerdata and you willbe able to modifier the data from the tableview
def exemple_table(self):
database = QSqlDatabase("QPSQL")
database.setHostName("localhost")
database.setDatabaseName("database")
database.setUserName("postgres")
database.setPassword("password")
database.open()
model_ft = QSqlTableModel(db=database)
model_ft.setTable('table')
model_ft.setHeaderData(0, Qt.Horizontal,"id")
model_ft.setHeaderData(1, Qt.Horizontal,"exemple01")
model_ft.setHeaderData(2, Qt.Horizontal,"exemple02")
model_ft.setHeaderData(3, Qt.Horizontal,"exemple03")
model_ft.setHeaderData(4, Qt.Horizontal,"exemple04")
model_ft.setHeaderData(5, Qt.Horizontal,"exemple05")
model_ft.setHeaderData(6, Qt.Horizontal,"exemple06")
model_ft.setHeaderData(7, Qt.Horizontal,"exemple07")
model_ft.removeColumns(8,1)
date = str(datetime.date.today())
self.tableView.setModel(model_ft)
self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
model_ft.setSort(0, Qt.DescendingOrder)
model_ft.select()
filter_ft = "date_d ='%s' " % (date_1)
model_ft.setFilter(filter_ft)
ps im using postgresql you can find other drivers here https://doc.qt.io/qt-5/sql-driver.html
and the filtre you can use all the SQL function
Upvotes: 1
Reputation: 48231
You must implement headerData()
:
class DataModel(QtCore.QAbstractTableModel):
# ...
def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return 'Column {}'.format(section + 1)
return super().headerData(section, orientation, role)
Obviously you can set your own labels even with a simple list containing the labels you want to show.
Note that you should be very careful with naming new attributes to subclasses as they might already exist.
Most importantly, you should not overwrite self.data
.
Upvotes: 6