TableView нет отображения данных в таблице после переопределения QAbstractTableModel - PullRequest
1 голос
/ 06 октября 2019

Я не могу получить данные для отображения в моем QML TableView. Я определил два массива - заголовки и строки, которые я хочу показать в TableView, но пока безуспешно. Ниже приведен минимальный воспроизводимый пример.

engine.py

import os
import sys
from PySide2 import QtCore, QtGui, QtSql, QtQml
from Table import TbModel
from PySide2.QtWidgets import QApplication
if __name__ == "__main__":
    current_dir = os.path.dirname(os.path.realpath(__file__))
    app = QApplication(sys.argv)
    QtQml.qmlRegisterType(TbModel, "TbModel", 1, 0, "TbModel")
    engine = QtQml.QQmlApplicationEngine()
    qml_path = os.path.join( "main.qml")
    engine.load(QtCore.QUrl.fromLocalFile(qml_path))
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

main.qml

import QtQuick 2.13
import QtQuick.Window 2.2
import QtQuick.Controls 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls 2.13
import TbModel 1.0

ApplicationWindow {
    visible: true
    id: window
    width: Screen.width
    height: Screen.height
    Grid {

    width: 300
    height: 100
    visible: true
    spacing: 200
    TableView
    {
        id: idtable
        model: TbModel { }
    TableViewColumn {
        role: "sci" 
        title: "sci"
    }
    TableViewColumn {
        role: "year"
        title: "year"
    }
    TableViewColumn {
        role: "cont"
        title: "cont"
    }

        // Component.onCompleted: {

        //     var roles = model.roleNameArray()
        //                 for (var i = 0; i < model.columnCount(); i++)
        //     {
        //         var column = addColumn( Qt.createQmlObject(
        //             "import QtQuick.Controls 1.1; TableViewColumn {}",
        //             this) )
        //         column.role=roles[i]
        //         column.title=roles[i]

        //     }
        // }
    }

}
}

Table.py

from PySide2.QtCore import QAbstractTableModel, QModelIndex, QObject, Qt
from PySide2 import QtCore

class TbModel(QAbstractTableModel):
    def __init__(self, parent: QObject = None) -> None:
        super().__init__(parent)
        self.headers = ["sci", "year", "cont"]
        self.rows =    [("Newton", "1643-01-04", "Classical mechanics"),
           ("Einstein", "1879-03-14", "Relativity"),
           ("Darwin", "1809-02-12", "Evolution")]

    def rowCount(self, parent=QModelIndex()):
        return len(self.rows)

    def columnCount(self, parent=QModelIndex()):
        return len(self.headers)

    def data(self, index, role):
        if role != Qt.DisplayRole:
            return None
        return self.rows[index.row()][index.column()]

    def headerData(self, section, orientation, role) :
        if role != Qt.DisplayRole:
            return None

        if section < 0 or section >= len(self.headers):
            return None

        return self.headers[section]

    def roleNames(self):
        roles = {
            Qt.UserRole + 1 : 'sci',
            Qt.UserRole + 2 : 'year',
            Qt.UserRole + 3 : 'cont'
        }
        return roles


    @QtCore.Slot(result="QVariantList")
    def roleNameArray(self):
        names = []
        names=self.headers

        return names

Я могу выбрать строки в TableView, но яне могу увидеть данные. Любая помощь приветствуется.

1 Ответ

2 голосов
/ 06 октября 2019

Ваш код содержит 2 ошибки:

  • В C ++ roleNames() метод возвращает QHash<int, QByteArray>, поэтому в Python вы должны вернуть словарь, ключ которого является целым числом, а значение должно бытьbytes или QByteArray, но в вашем случае значение является строкой.

  • Метод данных должен предоставлять информацию, требуемую представлением, и в этом случае они являются связанными ролями. с "sci", "year" и "cont", значения которых Qt.UserRole + 1, Qt.UserRole + 2 и Qt.UserRole + 3 отличаются от Qt.DisplayRole, но в вашей логике любое значение, отличное от Qt.DisplayRole, будет иметь значение None, противоречащеевыше.

  • QML предлагает несколько TableView: QtQuick.Controls 1.x и QtQuick . В вашем случае вы используете первый, который не требует в качестве модели QAbstractTableModel, а только QAbstractListModel, так как QModelIndex, используемый представлением, всегда будет иметь значение столбца в 1.

  • Учитывая вышесказанное, у вас могут возникнуть проблемы, поскольку QML предлагает несколько элементов с одинаковыми именами, которые принадлежат разным пакетам, для решения этой проблемы используется пространство имен.

Учитывая вышеизложенное,решение:

from PySide2.QtCore import QAbstractListModel, QModelIndex, QObject, Qt, Slot


class TbModel(QAbstractListModel):
    def __init__(self, parent: QObject = None) -> None:
        super().__init__(parent)
        self.headers = ["sci", "year", "cont"]
        self.rows = [
            ("Newton", "1643-01-04", "Classical mechanics"),
            ("Einstein", "1879-03-14", "Relativity"),
            ("Darwin", "1809-02-12", "Evolution"),
        ]

    def rowCount(self, parent=QModelIndex()):
        return len(self.rows)

    def data(self, index, role=Qt.DisplayRole):
        row = index.row()
        if 0 <= row < self.rowCount():
            if role in self.roleNames():
                name_role = self.roleNames()[role].decode()
                col = self.headers.index(name_role)
                return self.rows[row][col]

    def headerData(self, section, orientation, role):
        if role == Qt.DisplayRole and 0 <= section < len(self.headers):
            return self.headers[section]

    def roleNames(self):
        roles = {}
        for i, header in enumerate(self.headers):
            roles[Qt.UserRole + i + 1] = header.encode()
        return roles

    @Slot(result="QVariantList")
    def roleNameArray(self):
        return self.headers
import QtQuick 2.13
import QtQuick.Window 2.13
import QtQuick.Controls 1.4 as QQC1

import TbModel 1.0

QQC1.ApplicationWindow {
    id: window
    visible: true
    width: Screen.width
    height: Screen.height

    QQC1.TableView
    {
        id: idtable
        width: 600
        height: 300
        model: TbModel{ }
        QQC1.TableViewColumn {
            role: "sci" 
            title: "sci"
        }
        QQC1.TableViewColumn {
            role: "year"
            title: "year"
        }
        QQC1.TableViewColumn {
            role: "cont"
            title: "cont"
        }
    }
}

Выход:

enter image description here

...