Table view in qt quick with Python
-
Hi.
I am learning qt quick with Python. I have a basic project where I am trying to display a pandas dataframe in a TableView when the button is clicked. I am so far unable to achieve this seemingly simple goal.
Here's my main_window.py that acts as a backend:from PySide6.QtQml import QmlElement, qmlRegisterType from PySide6.QtCore import QObject, Signal, Slot, Property import pandas as pd from backend.utils import resource_path from backend.data_models import PandasModel QML_IMPORT_NAME = "main_window" QML_IMPORT_MAJOR_VERSION = 1 qmlRegisterType(PandasModel, "App", 1, 0, "PandasModel") @QmlElement class MainWindow(QObject): loadDataButtonClicked = Signal(PandasModel) @Slot() def load_data(self): df = pd.read_csv(resource_path("data/ssi_template.csv"), low_memory=False) print(df.head()) model = PandasModel(df) print(model.roleNames()) self.loadDataButtonClicked.emit(model)
This is my model in another .py file:
from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt class PandasModel(QAbstractTableModel): def __init__(self, df, parent=None): super().__init__(parent) self._dataframe = df def rowCount(self, parent=QModelIndex()): return len(self._dataframe) def columnCount(self, parent=QModelIndex()): return len(self._dataframe.columns) def roleNames(self): roles = {} for i, column in enumerate(self._dataframe.columns): roles[Qt.UserRole + i + 1] = column.encode('utf-8') return roles def data(self, index, role=Qt.ItemDataRole.DisplayRole): if not index.isValid(): return None if role == Qt.ItemDataRole.DisplayRole: value = self._dataframe.iloc[index.row(), index.column()] return str(value) if value is not None else "" return None def headerData(self, section, orientation, role=Qt.ItemDataRole): """ Return dataframe index as vertical header data and columns as horizontal header data. """ if role == Qt.ItemDataRole.DisplayRole: if orientation == Qt.Orientation.Horizontal: return str(self._dataframe.columns[section]) if orientation == Qt.Vertical: return str(self._dataframe.index[section]) return None
and here is App.qml:
// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls import Qt.labs.qmlmodels import DataViewer import main_window Window { id: mainWindow width: Screen.width height: Screen.height visible: true visibility: Window.Maximized title: "DataViewer" MainScreenForm { //This is from QDS UI file id: mainScreen anchors.fill: parent } MainWindow { // This is Python backend id: main_window } TableView { parent: mainScreen.table_rect id: tableView anchors.fill: parent model = null // Initially it's null // Rest of code goes here } Connections { target: mainScreen.load_data_btn function onClicked() { main_window.load_data() } } Connections { target: main_window function onLoadDataButtonClicked() { tableView.model = main_window.model // Setting the model to the TableView when the button is clicked } } }
I could not find relevant info in qt documentation/tutorials, on forums, and even LLMs like chatgpt or gemini could not help me.
Can anyone explain what am I doing wrong so far and how should I proceed?
Even better if someone can provide full example. -
What exactly is not working? - The QML_IMPORT_NAME should be the module name and it should be consistent for MainWindow and PandasModel . The qmlRegisterType() should not be required, importing PandasModel should suffice.
For examples, see https://doc.qt.io/qtforpython-6/examples/example_qml_usingmodel.html#example-qml-usingmodel , https://doc.qt.io/qtforpython-6/examples/example_qml_editingmodel.html and others.
-
@friedemannkleint The data that the model provides is not displayed in the tableview. When button is clicked, it should be emitting signal with the model that carries the data, so model=null is turned into model=actual data, then the data should be displayed on tableview. As you can see I've left part of the TableView block empty so someone could suggest the solution to this.