如何使用pyQt在qml中的python文件中显示QAbstractTableModel

Posted

技术标签:

【中文标题】如何使用pyQt在qml中的python文件中显示QAbstractTableModel【英文标题】:how to display a QAbstractTableModel in python file in qml using pyQt 【发布时间】:2018-01-16 11:00:38 【问题描述】:

我创建了一个 QAbstactTableModel 子类并将其与 qml 中的 tableview 绑定。我需要对 python 文件而不是 c++ 做同样的事情。我怎样才能做到这一点。我不太了解python。表视图.py

from os import path
import PyQt5
from PyQt5.QtCore import *
from PyQt5.QtCore import pyqtProperty, QObject, pyqtSignal
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtCore import pyqtProperty, QCoreApplication, QObject, QUrl
from PyQt5.QtQml import qmlRegisterType, QQmlComponent, QQmlEngine, QQmlListProperty
from PyQt5.QtCore import QTimer, pyqtSignal,pyqtSlot
from PyQt5.QtQml import QQmlListProperty
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQuick import QQuickView
class TableModel(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        super(TableModel, self).__init__()
        self.datatable = None

    def update(self, dataIn):
        print ('Updating Model')
        self.datatable = dataIn

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

    def columnCount(self, parent=QModelIndex()):
        return len(self.datatable.columns.values)

    def data(self, index, role=Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole:
            i = index.row()
            j = index.column()
            return '0'.format(self.datatable.iget_value(i, j))
        else:
            return QtCore.QVariant()

    def flags(self, index):
        return QtCore.Qt.ItemIsEnabled
class MainWindow(QQuickView):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.tablemodel=TableModel()
        self.rootContext().setContextProperty('PersonModel', self.tablemodel)
        self.rootContext().setContextProperty('MainWindow', self)
        self.setSource(QUrl('main.qml'))

myApp = QApplication(sys.argv)
ui = MainWindow()
ui.show()
sys.exit(myApp.exec_())

main.qml

import QtQuick 2.3
import QtQuick.Window 2.2
import QtQuick.Controls 1.4

Window 
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    TableView 
        id: idTableView
        anchors.fill: parent
        model: PersonModel

        Component.onCompleted: 
            console.log("column count", columnCount)
            console.log("model column count", PersonModel.columnCount())

            for (var i = 0; i < PersonModel.columnCount(); i++)
            
                var myTableViewColumn;
                var component = Qt.createComponent("MyTableViewColumn.qml")

                if (component.status === Component.Ready)
                
                    myTableViewColumn = component.createObject();
                

                if (null !== myTableViewColumn)
                
                    console.log("add column")
                   // myTableViewColumn.role = dataModel.modelRoles[i]
                   // myTableViewColumn.title = dataModel.modelRoles[i]
                    idTableView.addColumn(myTableViewColumn)
                
            
        
    

    Button 
        text: "click"
        anchors.bottom: parent.bottom
        onClicked: 
            idTableView.addColumn(idColumnComponent)
        
    

    Component 
        id: idColumnComponent

        TableViewColumn 
            id: idColumn
        
    



当我运行此代码时,我收到类似 return len(self.datatable.index) 的错误 AttributeError: 'NoneType' 对象没有属性 'index'

【问题讨论】:

好的,所以你希望有人为你写代码? 很抱歉问题不完整 【参考方案1】:

问题是datatable是None所以它没有列或索引(我不知道datatable是什么类型的结构),解决方法是为rowCount()columnCount()设置一个大小0如果是 None 否则我们分别通过 indexcolumns

另一个问题是你不应该使用QQuickView,因为你在.qml中除了Window之外生成另一个topLevel,所以会出现2个窗口,你应该只使用QQmlApplicationEngine

class TableModel(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        super(TableModel, self).__init__()
        self.datatable = None

    def update(self, dataIn):
        print ('Updating Model')
        self.datatable = dataIn

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

    def columnCount(self, parent=QModelIndex()):
        return len(self.datatable.columns.values) if self.datatable else 0

    def data(self, index, role=Qt.DisplayRole):
        if role == Qt.DisplayRole:
            i = index.row()
            j = index.column()
            return '0'.format(self.datatable.iget_value(i, j))
        else:
            return QVariant()

    def flags(self, index):
        return Qt.ItemIsEnabled

if __name__ == '__main__':
    import sys

    myApp = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    tablemodel=TableModel()
    engine.rootContext().setContextProperty('PersonModel', tablemodel)
    engine.load(QUrl.fromLocalFile(QDir.current().absoluteFilePath('main.qml')))
    if len(engine.rootObjects()) == 0:
        sys.exit(-1)
    sys.exit(myApp.exec_())

【讨论】:

我的数据表是一个字典数组 self.datatable = [ 'value1': 10, 'value2': 17, 'value3': 16, 'value4': 10, 'value1 ':11,'value2':13,'value3':17,'value4':16,'value1':12,'value2':15,'value3':12,'value4':12,]

以上是关于如何使用pyQt在qml中的python文件中显示QAbstractTableModel的主要内容,如果未能解决你的问题,请参考以下文章

如何正确地将 ComboBox 的模型从 python (pyQt5) 传递给 QML?

PyQt 和 QML:如何在一个插槽或函数中处理多个信号

使用 PyInstaller 在 --onefile 中使用 QML 构建 PyQt5

PyQt5 和 QML 中的嵌套 ListView

如何在 Python 中测试 QtQuick Qml

PyQt5 中的前后端分离与 QML