How to binding QAbstractTableModel and QML TableView ?
-
Hi All ,
I would like create sample qt application that can extract data from python object to QML tableview .
So i search from google and than implement QAbstractTableModel my self .
Unfortunately , it don't work .
Please check source code first , bottom is my source code show what i doing .
Program most time report Segmentation fault : 11
In some time it can successful execute but empty result .
If i change setContextProperty timing from before load to after load QML . Program is fire . data , role names , rowCount ..etc. All thing has been invoked , just but no result to display .
If i don't using QML , just create QTableView is coding , everything is fire now .
But unfortunately again , i must use QML .
Any people can let me know what i wrong ??
My Source code here , DummyList is my implementation of QAbstractTableModel
import sys import collections from PyQt5 import Qt class DummyList(Qt.QAbstractTableModel): __DEFAULT__ = Qt.QVariant() def __init__(self,*args,**kwargs): super(DummyList,self).__init__(*args,**kwargs) self.__roles = {} self.__data = [] self.append_data( [ ("hello_would", "HELOOWOULD",), ("foobar" , "ECHO",), ("zebra" , "FOO",), ("ummmm" , "BAR",) ],True ) def append_data(self,value,header_update=False): last_index = self.rowCount() self.beginInsertRows(Qt.QModelIndex(),last_index,last_index) value = collections.OrderedDict(value) self.__data.append(value) self.endInsertRows() if header_update: for key in value.keys(): if key not in self.__roles.values(): self.__roles[ Qt.Qt.UserRole + len(self.__roles) ] = key def headerData(self,section,orientation,role): if role == Qt.Qt.DisplayRole: column = self.__roles.get(Qt.Qt.UserRole + section,Qt.QVariant()) else: column = self.__roles.get(role,Qt.QVariant()) return column def columnCount(self,parent=Qt.QModelIndex()): return len(self.__data[0]) def rowCount(self,parent=Qt.QModelIndex()): return len(self.__data) def roleNames(self): """ Model only invoked while binding to QML view . """ default_roles = super(DummyList,self).roleNames() default_roles.update({ key:Qt.QByteArray(value.encode()) for key,value in self.__roles.items()}) return default_roles def data(self,index,role): row = index.row() if index.isValid(): if role >= Qt.Qt.UserRole: """ Only fire on binding to QML """ column = self.__roles[role] elif role == Qt.Qt.DisplayRole: column = self.__roles[Qt.Qt.UserRole + index.column()] else: return DummyList.__DEFAULT__ col_data = self.__data[row][column] return Qt.QVariant(col_data) else: return DummyList.__DEFAULT__ class MyWindow(Qt.QWidget): def __init__(self, *args): Qt.QWidget.__init__(self, *args) tablemodel = DummyList(self) tableview = Qt.QTableView() tableview.setModel(tablemodel) layout = Qt.QVBoxLayout(self) layout.addWidget(tableview) self.setLayout(layout) def main(*args,**kwargs): # We instantiate a QApplication passing the arguments of the script to it: main_app = Qt.QApplication(list(args)) """ Load tableview in QML , it will Segmentation fault: 11 or display empty table """ qml_app_engine = Qt.QQmlApplicationEngine( main_app ) qml_app_engine.rootContext().setContextProperty("tableModel",DummyList())#If set property here , raise segementation most time qml_app_engine.load(Qt.QUrl(sys.path[0]+"/hello_table.qml")) #qml_app_engine.rootContext().setContextProperty("tableModel",DummyList())#Nothing to show , but data method has been invoked new_root = qml_app_engine.rootObjects()[0] new_root.show() """ Load with custom create widget , everything is fine """ #w = MyWindow() #w.show() # Now we can start it. return_code = main_app.exec_() #del app.global_["qml_viewer"] return return_code if __name__ == "__main__": sys.exit(main(*sys.argv))
QML Source code :
import QtQuick 2.4 import QtQuick.Controls 1.3 import QtQuick.Window 2.2 import QtQuick.Dialogs 1.2 ApplicationWindow { //property var tableModel title: qsTr("Hello World") width: 640 height: 480 TableView { model: tableModel anchors.fill: parent Component.onCompleted: console.log(tableModel) TableViewColumn { width:200 role: "hello_would" title: "Hello Would" } TableViewColumn { width:200 role: "foobar" title: "Foobar" } TableViewColumn { width:200 role: "zebra" title: "Zebra" } TableViewColumn { width:200 role: "ummmm" title: "Ummmm" } } }