Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    How to binding QAbstractTableModel and QML TableView ?

    QML and Qt Quick
    qml python pyqt
    1
    1
    2593
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D
      David Ng last edited by David Ng

      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"
              }
      
          }
      
      
      }
      
      1 Reply Last reply Reply Quote 0
      • First post
        Last post