I'm trying to get auto-selection working in a QListView. I've been reading the Qt documentation, but I can't find a direct explanation on how to do it. I managed to get it working using QRect, but that doesn't feel like the right approach. How do you programmatically select an item in a QListView?
When you're working with Qt's Model/View architecture, there are times when you want to automatically select an item in a view — for example, after adding a new item to a list, you might want that item to appear selected. The Qt documentation covers selection models in detail, but the actual mechanism for doing this programmatically can be surprisingly hard to find if you don't know where to look.
The answer is setCurrentIndex(). Every view (including QListView) has this method, and it accepts a QModelIndex — the standard way Qt refers to a specific item in a model. Once you provide the right index, the view will select and highlight that item for you.
Understanding QModelIndex
In Qt's Model/View system, data lives in a model, and a view displays that data. To refer to a specific item in the model, Qt uses QModelIndex objects. You can think of a QModelIndex as an address — it tells the view exactly which row and column in the model you're talking about.
You create a QModelIndex by calling .index() on your model, passing in a row number and a column number:
index = model.index(row, column)
For a QListView, there's only one column, so the column is always 0.
Selecting an item with setCurrentIndex
Once you have a QModelIndex, you pass it to the view's setCurrentIndex() method. This tells the view to treat that item as the currently selected item.
Here's the pattern:
index = self.model.index(row, 0)
self.list_view.setCurrentIndex(index)
That's all there is to it. The view will update its display to show the item at row as selected.
A practical example: selecting the last item after adding
A common use case is selecting the most recently added item. For instance, if you have a to-do list and the user adds a new item, you probably want that new item to be highlighted right away.
PyQt/PySide Office Hours 1:1 with Martin Fitzpatrick — Save yourself time and frustration. Get one on one help with your projects. Bring issues, bugs and questions about usability to architecture and maintainability, and leave with solutions.
Here's a complete working example that demonstrates this. Each time you click the "Add Item" button, a new item is added to the list and automatically selected:
import sys
from PyQt6.QtCore import QAbstractListModel, Qt
from PyQt6.QtWidgets import (
QApplication,
QHBoxLayout,
QListView,
QPushButton,
QVBoxLayout,
QWidget,
)
class TodoModel(QAbstractListModel):
def __init__(self):
super().__init__()
self.todos = ["Buy groceries", "Walk the dog", "Write some code"]
def rowCount(self, parent=None):
return len(self.todos)
def data(self, index, role):
if role == Qt.ItemDataRole.DisplayRole:
return self.todos[index.row()]
def add_todo(self, text):
self.beginInsertRows(self.index(len(self.todos), 0), len(self.todos), len(self.todos))
self.todos.append(text)
self.endInsertRows()
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Auto-Select Example")
self.model = TodoModel()
self.list_view = QListView()
self.list_view.setModel(self.model)
self.add_button = QPushButton("Add Item")
self.add_button.clicked.connect(self.add_item)
self.select_first_button = QPushButton("Select First")
self.select_first_button.clicked.connect(self.select_first)
self.select_last_button = QPushButton("Select Last")
self.select_last_button.clicked.connect(self.select_last)
button_layout = QVBoxLayout()
button_layout.addWidget(self.add_button)
button_layout.addWidget(self.select_first_button)
button_layout.addWidget(self.select_last_button)
button_layout.addStretch()
layout = QHBoxLayout()
layout.addWidget(self.list_view)
layout.addLayout(button_layout)
self.setLayout(layout)
self.item_counter = 0
def add_item(self):
self.item_counter += 1
self.model.add_todo(f"New item {self.item_counter}")
# Auto-select the newly added (last) item.
last_index = self.model.index(self.model.rowCount() - 1, 0)
self.list_view.setCurrentIndex(last_index)
def select_first(self):
if self.model.rowCount() > 0:
first_index = self.model.index(0, 0)
self.list_view.setCurrentIndex(first_index)
def select_last(self):
if self.model.rowCount() > 0:
last_index = self.model.index(self.model.rowCount() - 1, 0)
self.list_view.setCurrentIndex(last_index)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
Run this example and try clicking "Add Item" a few times. Each new item appears at the bottom of the list and is immediately selected. The "Select First" and "Select Last" buttons show how you can jump to any item by constructing the right QModelIndex.
How it works
The add_item method does two things:
- It adds a new string to the model via
add_todo(). - It builds a
QModelIndexfor the last row usingself.model.index(self.model.rowCount() - 1, 0)and passes that tosetCurrentIndex().
The expression self.model.rowCount() - 1 gives us the index of the last row (since rows are zero-indexed). The second argument, 0, is the column — which is always 0 for a list.
Using the selection model for more control
If you need more fine-grained control over selection — for example, selecting multiple items, or clearing the selection entirely — you can work with the view's selection model directly:
selection_model = self.list_view.selectionModel()
# Clear the current selection.
selection_model.clearSelection()
# Select a specific index.
from PyQt6.QtCore import QItemSelectionModel
index = self.model.index(2, 0)
selection_model.setCurrentIndex(index, QItemSelectionModel.SelectionFlag.ClearAndSelect)
The QItemSelectionModel.SelectionFlag.ClearAndSelect flag tells the selection model to clear any existing selection first, then select the specified index. This is useful when you want to make sure only one item is selected at a time.
For most cases, though, calling setCurrentIndex() directly on the view is the simplest and most readable approach.
Summary
To programmatically select an item in a QListView (or any Qt view):
- Get a
QModelIndexfrom your model usingmodel.index(row, column). - Pass that index to
view.setCurrentIndex(index).
There's no need to work with QRect or any geometry-based approach. The QModelIndex and setCurrentIndex() combination is the standard, clean way to handle programmatic selection in Qt's Model/View architecture. If you're working with tabular data, the same approach applies to QTableView with numpy and pandas. For a deeper understanding of how signals and slots connect user interactions to your application logic, see our dedicated tutorial.
Bring Your PyQt/PySide Application to Market — Specialized launch support for scientific and engineering software built using Python & Qt.