j.Doe
j.Doe

Reputation: 212

Get selected index in QListView using QStandardItemModel

I am creating a QListView and QStandardItemModel using this code:

self.listView = QtWidgets.QListView(self.groupBox2)
self.listView.setGeometry(QtCore.QRect(200, 20, 400, 220))
self.entry = QtGui.QStandardItemModel()

I am adding items in a loop using something similar to:

self.item1 = QtGui.QStandardItem("Itemname1")
self.entry.appendRow(self.item1)
self.item2 = QtGui.QStandardItem("Itemname2")
self.entry.appendRow(self.item2)

How can I assign those items to a list knowing 0 in the list stands for "Itemname1", 1 stands for "Itemname2" etc.?

Also, how can I set an item in the QListView as selected? setSelected() doesn't seem to exist for QStandardItemModel

Upvotes: 2

Views: 8387

Answers (2)

eyllanesc
eyllanesc

Reputation: 244301

QStandardItemModel is a model so you can use all the methods of QAbstractItemModel as rowCount() that tells us the number of rows, so you iterate over them and using the item() method you get the QStandarItem associated with each index, and then use the text() method of the QStandarItem to get the text.

l = [self.entry.item(i).text() for i in range(self.entry.rowCount())]
print(l)

On the other hand if you want to select an element of a view that inherits from QAbstractItemView as in this case QListView you must use the QItemSelectionModel associated with the view that will be obtained using the method selectionModel(). The QItemSelectionModel has several methods to select and deselect in different ways, in this case you must use the method select and pass the flag QItemSelectionModel::Select. On the other hand, by default the views are enabled to select a single element, if you want more elements to be selected you must use the setSelectionMode() method and pass it the flag QAbstractItemView::MultiSelection.

Example:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        lay = QtWidgets.QVBoxLayout(self)
        button = QtWidgets.QPushButton("to list")
        button.clicked.connect(self.modelToList)
        self.listView = QtWidgets.QListView()
        lay.addWidget(button)
        lay.addWidget(self.listView)

        self.entry = QtGui.QStandardItemModel()
        self.listView.setModel(self.entry) 

        for text in ("Itemname1", "Itemname2", "Itemname3", "Itemname4"):
            it = QtGui.QStandardItem(text)
            self.entry.appendRow(it)

        self.listView.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
        sm = self.listView.selectionModel()
        for item in (self.entry.item(1), self.entry.item(2)):
            index = self.entry.indexFromItem(item)
            sm.select(index, QtCore.QItemSelectionModel.Select)

    def modelToList(self):
        l = [self.entry.item(i).text() for i in range(self.entry.rowCount())]
        print(l)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

If you only want to select an item then you must use setCurrentIndex() since it internally calls the select() method of selectionModel().

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from random import randint


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        lay = QtWidgets.QVBoxLayout(self)
        button = QtWidgets.QPushButton("to list")
        button.clicked.connect(self.modelToList)
        self.listView = QtWidgets.QListView()
        lay.addWidget(button)
        lay.addWidget(self.listView)

        self.entry = QtGui.QStandardItemModel()
        self.listView.setModel(self.entry) 

        for text in ("Itemname1", "Itemname2", "Itemname3", "Itemname4"):
            it = QtGui.QStandardItem(text)
            self.entry.appendRow(it)

        item = self.entry.item(randint(0, self.entry.rowCount()-1))
        self.listView.setCurrentIndex(self.entry.indexFromItem(item))

    def modelToList(self):
        l = [self.entry.item(i).text() for i in range(self.entry.rowCount())]
        print(l)


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

Upvotes: 4

S. Nick
S. Nick

Reputation: 13691

Try it:

import sys
from PyQt5       import QtWidgets, QtGui, QtCore
from PyQt5.QtGui import QBrush, QColor 

class Widget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        lay = QtWidgets.QVBoxLayout(self)

        self.listView = QtWidgets.QListView()
        self.label    = QtWidgets.QLabel("Please Select item in the QListView")
        lay.addWidget(self.listView)
        lay.addWidget(self.label)

        self.entry = QtGui.QStandardItemModel()
        self.listView.setModel(self.entry)

        self.listView.clicked[QtCore.QModelIndex].connect(self.on_clicked)
        # When you receive the signal, you call QtGui.QStandardItemModel.itemFromIndex() 
        # on the given model index to get a pointer to the item        

        for text in ["Itemname1", "Itemname2", "Itemname3", "Itemname4"]:
            it = QtGui.QStandardItem(text)
            self.entry.appendRow(it)
        self.itemOld = QtGui.QStandardItem("text")

    def on_clicked(self, index):
        item = self.entry.itemFromIndex(index)
        self.label.setText("on_clicked: itemIndex=`{}`, itemText=`{}`"
                           "".format(item.index().row(), item.text()))
        item.setForeground(QBrush(QColor(255, 0, 0))) 
        self.itemOld.setForeground(QBrush(QColor(0, 0, 0))) 
        self.itemOld = item

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

enter image description here

Upvotes: 1

Related Questions