Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I was able to load csv file and display it as Tableview in Python QML QT GUI. The Sample tabview.py is as follows

from os.path import dirname, realpath, join
from PySide2.QtWidgets import QApplication, QWidget
from PySide2.QtCore import QFile
from PySide2.QtUiTools import QUiLoader
from PySide2.QtUiTools import *
from PySide2.QtCore import QFile
from PySide2.QtUiTools import *
import numpy as np
import pandas as pd

scriptDir = dirname(realpath(__file__))

class DataFrameModel(QtCore.QAbstractTableModel):
    DtypeRole = QtCore.Qt.UserRole + 1000
    ValueRole = QtCore.Qt.UserRole + 1001

def __init__(self, df=pd.DataFrame(), parent=None):
    super(DataFrameModel, self).__init__(parent)
    self._dataframe = df

def setDataFrame(self, dataframe):
    self.beginResetModel()
    self._dataframe = dataframe.copy()
    self.endResetModel()

def dataFrame(self):
    return self._dataframe

dataFrame = QtCore.pyqtProperty(pd.DataFrame, fget=dataFrame, fset=setDataFrame)

@QtCore.pyqtSlot(int, QtCore.Qt.Orientation, result=str)
def headerData(self, section: int, orientation: QtCore.Qt.Orientation, role: int = QtCore.Qt.DisplayRole):
    if role == QtCore.Qt.DisplayRole:
        if orientation == QtCore.Qt.Horizontal:
            return self._dataframe.columns[section]
        else:
            return str(self._dataframe.index[section])
    return QtCore.QVariant()

def rowCount(self, parent=QtCore.QModelIndex()):
    if parent.isValid():
        return 0
    return len(self._dataframe.index)

def columnCount(self, parent=QtCore.QModelIndex()):
    if parent.isValid():
        return 0
    return self._dataframe.columns.size

def data(self, index, role=QtCore.Qt.DisplayRole):
    if not index.isValid() or not (0 <= index.row() < self.rowCount() 
        and 0 <= index.column() < self.columnCount()):
        return QtCore.QVariant()
    row = self._dataframe.index[index.row()]
    col = self._dataframe.columns[index.column()]
    dt = self._dataframe[col].dtype

    val = self._dataframe.iloc[row][col]
    if role == QtCore.Qt.DisplayRole:
        return str(val)
    elif role == DataFrameModel.ValueRole:
        return val
    if role == DataFrameModel.DtypeRole:
        return dt
    return QtCore.QVariant()

def roleNames(self):
    roles = {
        QtCore.Qt.DisplayRole: b'display',
        DataFrameModel.DtypeRole: b'dtype',
        DataFrameModel.ValueRole: b'value'
    }
    return roles

if __name__ == "__main__":
   import os
   import sys

   app = QtGui.QGuiApplication(sys.argv)
   path = "C:/Users/kalya/Documents/untitled7/tele.csv"
   df = pd.read_csv(path)
   print(df)
   model = DataFrameModel(df)
   engine = QtQml.QQmlApplicationEngine()
   engine.rootContext().setContextProperty("table_model", model)
   qml_path = os.path.join(os.path.dirname(__file__), "main.qml")
   engine.load(QtCore.QUrl.fromLocalFile(qml_path))
   if not engine.rootObjects():
       sys.exit(-1)
   engine.quit.connect(app.quit)
   sys.exit(app.exec_())

and this is the tabview.qml

import QtQuick 2.12
import QtQuick.Controls 2.4
import QtQuick.Window 2.11

Window {
   visible: true
   width: 800
   height: 480
   title: qsTr("Load CSV")
   color: '#222222'

TableView {
    id: tableView

    columnWidthProvider: function (column) { return 100; }
    rowHeightProvider: function (column) { return 60; }
    anchors.fill: parent
    leftMargin: rowsHeader.implicitWidth
    topMargin: columnsHeader.implicitHeight
    model: table_model
    delegate: Rectangle {
        color: parseFloat(display) > 100 ? 'grey' : 'black'
        Text {
            text: display
            anchors.fill: parent
            anchors.margins: 10
            color: 'white'
            font.pixelSize: 10
            verticalAlignment: Text.AlignVCenter
        }
    }
    Rectangle { // mask the headers
        z: 3
        color: "#222222"
        y: tableView.contentY
        x: tableView.contentX
        width: tableView.leftMargin
        height: tableView.topMargin
    }

    Row {
        id: columnsHeader
        y: tableView.contentY
        z: 2
        Repeater {
            model: tableView.columns > 0 ? tableView.columns : 1
            Label {
                width: tableView.columnWidthProvider(modelData)
                height: 35
                text: table_model.headerData(modelData, Qt.Horizontal)
                color: '#aaaaaa'
                font.pixelSize: 15
                padding: 10
                verticalAlignment: Text.AlignVCenter

                background: Rectangle { color: "#333333" }
            }
        }
    }
    Column {
        id: rowsHeader
        x: tableView.contentX
        z: 2
        Repeater {
            model: tableView.rows > 0 ? tableView.rows : 1
            Label {
                width: 40
                height: tableView.rowHeightProvider(modelData)
                text: table_model.headerData(modelData, Qt.Vertical)
                color: '#aaaaaa'
                font.pixelSize: 15
                padding: 10
                verticalAlignment: Text.AlignVCenter

                background: Rectangle { color: "#333333" }
            }
         }
     }

      ScrollIndicator.horizontal: ScrollIndicator { }
      ScrollIndicator.vertical: ScrollIndicator { }
   }
 }

when i use the same above file as to display in stackview renaming main.py and main.qml to lets say tabview.py and tabview.qml and loading them from main.qml below

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtGraphicalEffects 1.15

Window {
   id: window
   width: 640
   height: 480
   visible: true
   color: "#000000"
   title: qsTr("Hello World")

Button {
    id: btnLoad
    text: qsTr("Main")
    anchors.left: parent.left
    anchors.right: stackView.left
    anchors.top: parent.top
    anchors.rightMargin: 0
    anchors.leftMargin: 0
    anchors.topMargin: 8
    onClicked: {
        stackView.push(Qt.resolvedUrl("settingsPage.qml"))
                                }
}
Button {
    id: btnmain
    text: qsTr("Load")
    anchors.left: parent.left
    anchors.right: stackView.left
    anchors.top: parent.top
    anchors.rightMargin: 0
    anchors.leftMargin: 0
    anchors.topMargin: 66
    onClicked: stackView.push(Qt.resolvedUrl("tabview.qml"))
}

StackView {
    id: stackView
    x: 112
    width: 510
    anchors.right: parent.right
    anchors.top: parent.top
    anchors.bottom: parent.bottom
    anchors.bottomMargin: 0
    anchors.rightMargin: 0
    anchors.topMargin: 0
    initialItem: Qt.resolvedUrl("settingsPage.qml")
}
Connections{
         target:backend}
}

the csv was not able to load. it throws the error file:///C:/Users/luffy/Documents/QTapp/qml/pages/tabview.qml:17: ReferenceError: table_model is not defined

the main.py is as follows

import sys
import os
import datetime
from os.path import dirname, realpath, join
from PySide2.QtWidgets import QApplication, QWidget
from PySide2.QtCore import QFile
from PySide2.QtUiTools import *
from PyQt5 import QtCore, QtGui, QtQml
from PySide2.QtCore import QFile
from PySide2.QtUiTools import *
import numpy as np
import pandas as pd
import tabview

from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import QObject, Slot, Signal, QTimer, QUrl

from PySide2.QtWidgets import QApplication, QMainWindow
from PySide2.QtCore import QFile

class MainWindow(QObject):
def __init__(self):
        QObject.__init__(self)


if __name__ == "__main__":
   app = QGuiApplication(sys.argv)
   engine = QQmlApplicationEngine()
   engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))

main = MainWindow()
engine.rootContext().setContextProperty("backend", main)

if not engine.rootObjects():
    sys.exit(-1)
sys.exit(app.exec_())

What am i doing wrong? Is there any alternative to load csv and display in QML QT GUI using python?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
496 views
Welcome To Ask or Share your Answers For Others

1 Answer

Your code has the following errors:

  • Only one of the if __name__ == "__main__": codes are executed (for more details read here), so if you execute the main file then the code where you export the model will not be executed and therefore it is not recognized as indicated by the error message.

  • You should not combine the PyQt5 and PySide2 libraries as you will have silent errors that are difficult to track.

  • You must improve the imports as they are also a source of errors that are difficult to debug.

  • StackView pages should not have a window as root but an Item.

Considering the above then the solution is:

├── main.py
├── models.py
├── qml
│?? ├── main.qml
│?? └── pages
│??     ├── settingsPage.qml
│??     └── tabview.qml
└── test.csv

main.py

import os.path
import sys

from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine

import pandas as pd

from models import DataFrameModel


CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))

if __name__ == "__main__":
    app = QGuiApplication(sys.argv)

    csv_path = os.path.join(CURRENT_DIR, "test.csv")
    df = pd.read_csv(csv_path)
    model = DataFrameModel(df)

    engine = QQmlApplicationEngine()
    engine.rootContext().setContextProperty("table_model", model)
    engine.load(os.path.join(CURRENT_DIR, "qml", "main.qml"))

    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

models.py

import pandas as pd

from PySide2.QtCore import Property, QAbstractTableModel, QModelIndex, Qt, Slot


class DataFrameModel(QAbstractTableModel):
    DtypeRole = Qt.UserRole + 1000
    ValueRole = Qt.UserRole + 1001

    def __init__(self, df=pd.DataFrame(), parent=None):
        super(DataFrameModel, self).__init__(parent)
        self._dataframe = df

    def setDataFrame(self, dataframe):
        self.beginResetModel()
        self._dataframe = dataframe.copy()
        self.endResetModel()

    def dataFrame(self):
        return self._dataframe

    dataFrame = Property(pd.DataFrame, fget=dataFrame, fset=setDataFrame)

    @Slot(int, Qt.Orientation, result=str)
    def headerData(
        self,
        section: int,
        orientation: Qt.Orientation,
        role: int = Qt.DisplayRole,
    ):
        if role == Qt.DisplayRole:
            if orientation == Qt.Horizontal:
                return self._dataframe.columns[section]
            else:
                return str(self._dataframe.index[section])

    def rowCount(self, parent=QModelIndex()):
        if parent.isValid():
            return 0
        return len(self._dataframe.index)

    def columnCount(self, parent=QModelIndex()):
        if parent.isValid():
            return 0
        return self._dataframe.columns.size

    def data(self, index, role=Qt.DisplayRole):
        if not index.isValid() or not (
            0 <= index.row() < self.rowCount()
            and 0 <= index.column() < self.columnCount()
        ):
            return
        row = self._dataframe.index[index.row()]
        col = self._dataframe.columns[index.column()]
        dt = self._dataframe[col].dtype

        val = self._dataframe.iloc[row][col]
        if role == Qt.DisplayRole:
            return str(val)
        elif role == DataFrameModel.ValueRole:
            return val
        if role == DataFrameModel.DtypeRole:
            return dt

    def roleNames(self):
        roles = {
            Qt.DisplayRole: b"display",
            DataFrameModel.DtypeRole: b"dtype",
            DataFrameModel.ValueRole: b"value",
        }
        return roles

main.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtGraphicalEffects 1.15

Window {
   id: window
   width: 640
   height: 480
   visible: true
   color: "#000000"
   title: qsTr("Hello World")

    Button {
        id: btnLoad
        text: qsTr("Main")
        anchors.left: parent.left
        anchors.right: stackView.left
        anchors.top: parent.top
        anchors.rightMargin: 0
        anchors.leftMargin: 0
        anchors.topMargin: 8
        onClicked: {
            stackView.push(Qt.resolvedUrl("pages/settingsPage.qml"))
        }
    }
    Button {
        id: btnmain
        text: qsTr("Load")
        anchors.left: parent.left
        anchors.right: stackView.left
        anchors.top: parent.top
        anchors.rightMargin: 0
        anchors.leftMargin: 0
        anchors.topMargin: 66
        onClicked: stackView.push(Qt.resolvedUrl("pages/tabview.qml"))
    }

    StackView {
        id: stackView
        x: 112
        width: 510
        anchors.right: parent.right
        anchors.top: parent.top
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 0
        anchors.rightMargin: 0
        anchors.topMargin: 0
        initialItem: Qt.resolvedUrl("pages/settingsPage.qml")
    }
}

tabview.qml

import QtQuick 2.12
import QtQuick.Controls 2.4

Item {
   width: 800
   height: 480

    TableView {
        id: tableView

        columnWidthProvider: function (column) { return 100; }
        rowHeightProvider: function (column) { return 60; }
        anchors.fill: parent
        leftMargin: rowsHeader.implicitWidth
        topMargin: columnsHeader.implicitHeight
        model: table_model
        delegate: Rectangle {
            color: parseFloat(display) > 100 ? 'grey' : 'black'
            Text {
                text: display
                anchors.fill: parent
                anchors.margins: 10
                color: 'white'
                font.pixelSize: 10
                verticalAlignment: Text.AlignVCenter
            }
        }
        Rectangle { // mask the headers
            z: 3
            color: "#222222"
            y: tableView.contentY
            x: tableView.contentX
            width: tableView.leftMargin
            height: tableView.topMargin
        }

        Row {
            id: columnsHeader
            y: tableView.contentY
            z: 2
            Repeater {
                model: tableView.columns > 0 ? tableView.columns : 1
                Label {
                    width: tableView.columnWidthProvider(modelData)
                    height: 35
                    text: table_model.headerData(modelData, Qt.Horizontal)
                    color: '#aaaaaa'
                    font.pixelSize: 15
                    padding: 10
                    verticalAlignment: Text.AlignVCenter

                    background: Rectangle { color: "#333333" }
                }
            }
        }
        Column {
            id: rowsHeader
            x: tableView.contentX
            z: 2
            Repeater {
                model: tableView.rows > 0 ? tableView.rows : 1
                Label {
                    width: 40
                    height: tableView.rowHeightProvider(modelData)
                    text: table_model.headerData(modelData, Qt.Vertical)
                    color: '#aaaaaa'
                    font.pixelSize: 15
                    padding: 10
                    verticalAlignment: Text.AlignVCenter

                    background: Rectangle { color: "#333333" }
                }
             }
         }

          ScrollIndicator.horizontal: ScrollIndicator { }
          ScrollIndicator.vertical: ScrollIndicator { }
       }
 }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...