问题
I was trying to Return an object in a role in Python and get a reference of another object in QML. Finally, I found I can use Property to do it.
But, I want to get a reference of another reference of another object in QML, PyQt just segfault. I switched to PySide but it was still crashing when I run it.
Did I doing something wrong?
GDB said
Cannot access memory at address 0xb
Cannot access memory at address 0x3
main.py
import sys
from PySide import QtCore, QtGui, QtDeclarative
from PySide.QtCore import Property, Signal, 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 UserItem(QtCore.QObject):
def __init__(self, item, parent=None):
super(UserItem, self).__init__()
self._data = item
@QtCore.Property(str)
def name(self):
return self._data.get('name')
class TweetItem(QObject):
roles = {
QtCore.Qt.UserRole + 1: 'id',
QtCore.Qt.UserRole + 6: 'original',
}
id_changed = Signal()
def __init__(self, id=None, original=None, author=None, parent=None):
QObject.__init__(self, parent=parent)
self._data = {'original': original,
'id': id, 'author': author}
def data(self, key):
return self._data[self.roles[key]]
@Property(str, constant=True)
def id(self):
return self._data['id']
@Property(QtCore.QObject, constant=True)
def original(self):
return self._data['original']
@Property(QtCore.QObject, constant=True)
def author(self):
return UserItem(self._data['author'])
if __name__ == "__main__":
model = TweetModel(TweetItem)
item = TweetItem("0001", None, {'name': 'test'}, model)
item_2 = TweetItem("0002", item, None, model)
item_3 = TweetItem("0003", item_2, None, model)
model.appendRow(item_3)
App = QtGui.QApplication(sys.argv)
view = QtDeclarative.QDeclarativeView()
view.rootContext().setContextProperty("mymodel", model)
view.setSource(QtCore.QUrl.fromLocalFile("main.qml"))
view.show()
App.exec_()
main.qml
import QtQuick 1.0
Rectangle {
width: 360
height: 360
ListView {
anchors.fill: parent
model: mymodel
delegate: Item {
Text {
text: id + " " + original.id + " " + original.original.author.name
}
}
}
}
回答1:
I think this is garbage collection issue.
Your UserItem that you make in author method isn't referenced anywhere afterwards in python code and gets garbage collected.
To avoid this, you can make UserItem in your main:
item = TweetItem("0001", None, UserItem({'name': 'test'}), model)
or store it in TweetItem upon creation:
if not self._author:
self._author = UserItem(self._data['author'])
return self._author
I'd probably do the first way or maybe pass dict to the TweetItem and convert it to UserItem in __init__:
self._data = {'original': original,
'id': id, 'author': UserItem(author)}
来源:https://stackoverflow.com/questions/16112136/pyqt-segfault-when-trying-to-get-a-sub-sub-property-in-qml