zadstofun | 2021-03-07 06:57:44 UTC | #1
I'm new and I need some assistance and pointers. I have gone through the turorials on QTableWidget however my data set is not List of List but List of Dicts.
My major headache is how to return values for the subclass of QAbstractTableModel Data Method.
My idea to loop through the dataset to generate the header as an ordered set of the dataset keys().
I will then can enumerate the header set to create a dict index of the headers.
Such that when I want to return values of the I cal do something like
return self._data[index.row()][header_dict[index.column()]]
Packaging Python Applications with PyInstaller by Martin Fitzpatrick — This step-by-step guide walks you through packaging your own Python applications from simple examples to complete installers and signed executables.
My Question:
Is there a shorter way other than having to using pandas or numpy
martin | 2021-03-09 09:27:26 UTC | #2
Hi @zadstofun welcome to the forum!
You don't need to use pandas or numpy to do this, but you do need some way to map your dictionary keys to numeric values -- Qt's models work on rows and columns.
What I would do is define a list of header values and/or dictionary keys. Then you can use the column index to get your key, and use this to get the data from the dictionary. For example --
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
class DictionaryTableModel(QtCore.QAbstractTableModel):
def __init__(self, data, headers):
super(DictionaryTableModel, self).__init__()
self._data = data
self._headers = headers
def data(self, index, role):
if role == Qt.DisplayRole:
# Look up the key by header index.
column = index.column()
column_key = self._headers[column]
return self._data[index.row()][column_key]
def rowCount(self, index):
# The length of the outer list.
return len(self._data)
def columnCount(self, index):
# The length of our headers.
return len(self._headers)
def headerData(self, section, orientation, role):
# section is the index of the column/row.
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal:
return str(self._headers[section])
if orientation == Qt.Vertical:
return str(section)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.table = QtWidgets.QTableView()
data = [
{'a':4, 'b':9, 'c':2},
{'a':1, 'b':0, 'c':0},
{'a':3, 'b':5, 'c':0},
{'a':3, 'b':3, 'c':2},
{'a':7, 'b':8, 'c':9},
]
headers = ['a', 'b', 'c']
self.model = DictionaryTableModel(data, headers)
self.table.setModel(self.model)
self.setCentralWidget(self.table)
app=QtWidgets.QApplication(sys.argv)
window=MainWindow()
window.show()
app.exec_()
If you want to show different headers to your keys you can - just create a separate list (e.g. _keys) and perform the data lookup on that instead.
zadstofun | 2021-03-11 06:20:59 UTC | #3
Hello Martin,
Thanks so much for taking timeout to respond.
I just did a little modification with permits for headers to be generated on the fly just as an added information to someone else that might need the code nothing much takes nothing away from your code.
Also for the value to return in the data I put a try except just in case the key does not exist in the row.
A dict.get could be used instead of the try except depending on preference.
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import Qt
class DictionaryTableModel(Qtore.QAbstractTableModel):
def __init__(self, data: Union[list, dict] = None):
super(DictionaryTableModel, self).__init__()
self.data = data or []
self._hdr = self.gen_hdr_data() if data else []
self._base_color = {'NewConnection': 'blue', }
def gen_hdr_data(self):
self._hdr = sorted(list(set().union(*(d.keys() for d in self.data))))
return self._hdr
def data(self, index: QModelIndex, role: int):
if role == Qt.DisplayRole:
try:
value = self.data[index.row()][self._hdr[index.column()]]
except KeyError:
value = None
return str(value) if value else ""
if role == Qt.BackgroundRole and self._base_color.get(
self.data[index.row()]['PRESENT_STATUS'], False):
# noinspection PyTypeChecker
_state = self._base_color[self.data[index.row()]['PRESENT_STATUS']]
return QColor(self._base_color[_state])
I have a new question but then I will use another Q&A as it has to do with Qt.BackgroudRole I will open another Q&A for that