QTableWidget for List of Dict

Heads up! You've already completed this tutorial.

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()]]

PyQt/PySide 1:1 Coaching with Martin Fitzpatrick — Get one on one help with your Python GUI projects. Working together with you I'll identify issues and suggest fixes, from bugs and usability to architecture and maintainability.

Book Now 60 mins ($195)

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 --

python
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt

class DictionaryTableModel(QtCore.QAbstractTableModel):
    def __init__(self, data, headers):
        super().__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.

Over 10,000 developers have bought Create GUI Applications with Python & Qt!
Create GUI Applications with Python & Qt5
Take a look

Downloadable ebook (PDF, ePub) & Complete Source code

Also available from Leanpub and Amazon Paperback

[[ discount.discount_pc ]]% OFF for the next [[ discount.duration ]] [[discount.description ]] with the code [[ discount.coupon_code ]]

Purchasing Power Parity

Developers in [[ country ]] get [[ discount.discount_pc ]]% OFF on all books & courses with code [[ discount.coupon_code ]]


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.

python
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt

class DictionaryTableModel(Qtore.QAbstractTableModel):

    def __init__(self, data: Union[list, dict] = None):
        super().__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

Create GUI Applications with Python & Qt6 by Martin Fitzpatrick — (PyQt6 Edition) The hands-on guide to making apps with Python — Over 10,000 copies sold!

More info Get the book


Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak
Martin Fitzpatrick

QTableWidget for List of Dict was written by Martin Fitzpatrick .

Martin Fitzpatrick has been developing Python/Qt apps for 8 years. Building desktop applications to make data-analysis tools more user-friendly, Python was the obvious choice. Starting with Tk, later moving to wxWidgets and finally adopting PyQt. Martin founded PythonGUIs to provide easy to follow GUI programming tutorials to the Python community. He has written a number of popular https://www.martinfitzpatrick.com/browse/books/ on the subject.