I am using PyQt 5.9.1, and I want to connect QListView.currentChanged to a function at runtime. But for some reason, I can do it only before calling setModel()
. If I call setModel()
(even with a None
argument) beforehand, then my currentChanged
function is never called.
# https://www.pythoncentral.io/pyside-pyqt-tutorial-qlistview-and-qstandarditemmodel/
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
def currentChanged(current, previous):
print(current, previous)
app = QApplication(sys.argv)
model = QStandardItemModel()
foods = [
'Cookie dough', # Must be store-bought
'Hummus', # Must be homemade
'Spaghetti', # Must be saucy
'Dal makhani', # Must be spicy
'Chocolate whipped cream' # Must be plentiful
]
for food in foods:
item = QStandardItem(food)
model.appendRow(item)
list = QListView()
list.setWindowTitle('Honey-Do List')
list.setMinimumSize(600, 400)
list.currentChanged = currentChanged # BEFORE setModel
list.setModel(model)
list.show()
app.exec_()
Whenever setModel()
is called, a new selection model is created. Internally, the currentChanged signal of the new selection model is then connected to the protected currentChanged slot of the list-view. Thus, whenever a data model is set, the existing internal signal connections are automatically disconnected and reconnected. In your example, when you monkey-patch currentChanged
after calling setModel()
, the internal signal connections will not be re-made, and so your function will never be called.
In general, it is usually a mistake to make changes to a view before setting any of its models, because there are likely to be unpredictable internal side-effects which won't always be documented.
You should also note that it is not necessary to monkey-patch currentChanged
at all. The correct way to do things is like this:
list = QListView()
list.setModel(model)
list.selectionModel().currentChanged.connect(currentChanged)
This will work in exactly the same way as your current code.