9

Same exact problem as this: Connecting QTableView selectionChanged signal produces segfault with PyQt

I have a QListView, and I want to call a function when an item is selected:

self.server_list = QtGui.QListView(self.main_widget)
self.server_list_model = QtGui.QStandardItemModel()
self.server_list.setModel(self.server_list_model)
self.server_list.selectionModel().selectionChanged.connect(self.server_changed)

But, when it reaches the last line, where I'm using the selection model, the app crashes. Not with a traceback, but with a "appname has stopped working" from Windows. I'm pretty sure that's a segfault.

BUT, when I use PyQt4 it works fine. I'm using PySide because it's LGPL.

Yes, I'm on the latest versions of everything (PySide: 1.2.1, Python 2.7.5, Qt 4.8.5).

Can anyone help me with this?

Community
  • 1
  • 1
user1438098
  • 2,239
  • 3
  • 18
  • 14

2 Answers2

14

Try holding a reference to the selection model for the lifetime of the selection model. That worked for me with a similar problem (seg fault when connecting to currentChanged event on a table views selection model).

self.server_list = QtGui.QListView(self.main_widget)
self.server_list_model = QtGui.QStandardItemModel()
self.server_list.setModel(self.server_list_model)
self.server_list_selection_model = self.server_list.selectionModel() # workaround
self.server_list_selection_model.selectionChanged.connect(self.server_changed)

For some reason, the last two lines work, while combining them into one command throws an error.

Valakyr
  • 151
  • 1
  • 5
  • This worked for me too. (I used self.server_list_selection_model in the last line instead of self.server_list.selectionModel().) But why does this work and does the code in the question not work? – Gijs van Oort Feb 17 '14 at 10:20
  • You're right, that should be self.server_list_selectionModel in the last line. I'll correct that. I don't quite understand it myself, but the issue is caused by the reference-counting garbage collection implementation of qt interacting (or rather not interacting) with the pyside bindings. – Valakyr Feb 24 '14 at 20:10
  • If you don't like to keep a reference to the selection model you could use the old fashioned signal wiring syntax: `QtCore.QObject.connect(self.server_list.selectionModel(), QtCore.SIGNAL("currentChanged(QModelIndex, QModelIndex)"), self.server_changed)`. I don't know if there are any traps when keeping the selection model. But I prefer writing `selectionChanged.connect(self.server_changed)`, like you do it, too. – this.myself Jun 02 '14 at 11:24
3

Same problem here: http://permalink.gmane.org/gmane.comp.lib.qt.pyside.devel/541

And I also answered: http://permalink.gmane.org/gmane.comp.lib.qt.pyside.devel/542

I suspect what happens is:

self.server_list # local object
.selectionModel() # call C++ method, wraps C++ object in Python object
.selectionChanged # get property of object
# selection model is now out of scope and gets garbage collected
.connect(...) # OOPS! ...operating on object that no longer exists!
Matthew
  • 2,593
  • 22
  • 25