Return an object in a role in Python and get a reference of another object in QML

后端 未结 3 1607
粉色の甜心
粉色の甜心 2021-01-07 10:29

I\'m writing a Twitter client. I implemented TweetItem and TweetModel. The issue is that there is a role in TweetItem called ori

相关标签:
3条回答
  • 2021-01-07 10:50

    My guess is that you got undefined not on accessing your TweetItem object, but on trying to get id out of it.

    As it looks, your implementation of QAbstractItemModel in TweetItem is simply incorrect. Not does it's data method accepts any index, nor it implements rowCount. Consult Qt documentation on how to implement QAbstractItemModel interface correctly if you still wan't to use it.

    My advice, to achieve what you want, is to subclass QObject instead and provide your additional data as it's named properties to use them in QML. See this page of Qt guidelines on how to bind your QObject with QML.

    0 讨论(0)
  • 2021-01-07 11:05
    1. Straight answer: you got undefined because, because your TweetItem.original is in fact None.
    2. I'm not sure what you are trying to accomplish, but I want to clear some possible misunderstandings. QAbstractItemModel is a model class too, it's somewhat strange to see

      def data(self, index, role):
          return self.tweets[index.row()].data(role)
      

    there.

    0 讨论(0)
  • 2021-01-07 11:09

    As was suggested by dant3 use QObject with properties.

    Here is an example how to do it:

    import sys
    from PyQt4 import QtCore, QtGui, QtDeclarative
    from PyQt4.QtCore import pyqtProperty, pyqtSignal, QObject
    
    
    class TweetModel(QtCore.QAbstractListModel):
        def __init__(self, prototype, parent=None):
            QtCore.QAbstractListModel.__init__(self, parent)
            self.setRoleNames(prototype.roles)
            self.tweets = []
    
        def appendRow(self, item):
            self.tweets.append(item)
    
        def rowCount(self, parent=QtCore.QModelIndex()):
            return len(self.tweets)
    
        def data(self, index, role):
            return self.tweets[index.row()].data(role)
    
    
    class TweetItem(QObject):
        roles = {
            QtCore.Qt.UserRole + 1: 'id',
            QtCore.Qt.UserRole + 6: 'original',
        }
    
        id_changed = pyqtSignal()
    
        def __init__(self, id=None, original=None, parent=None):
            QObject.__init__(self, parent=parent)
    
            self._data = {'original': original}
            self.id = id
    
        def data(self, key):
            return self._data[self.roles[key]]
    
        @pyqtProperty(str, notify=id_changed)
        def id(self):
            return self._data['id']
    
        @id.setter
        def id(self, value):
            if self._data.get('id') != value:
                self._data['id'] = value
                self.id_changed.emit()
    
    if __name__ == "__main__":
        model = TweetModel(TweetItem)
        item = TweetItem("0001", None, model)
        model.appendRow(TweetItem("0002", item, model))
    
        App = QtGui.QApplication(sys.argv)
        view = QtDeclarative.QDeclarativeView()
        view.rootContext().setContextProperty("mymodel", model)
        view.setSource(QtCore.QUrl.fromLocalFile("main.qml"))
        view.show()
        App.exec_()
    

    The QML file remains the same.

    I didn't make original a property, since you get it as model data, but you can make it in the same fashion as id.

    0 讨论(0)
提交回复
热议问题