PyQt Model/View

Summary: in this tutorial, you’ll learn how the PyQt Model/View pattern works and its advantages.

Introduction to PyQt Model/View pattern

Model-View-Controller or MVC is a software pattern for developing user interfaces (UI). The MVC pattern decouples UI (views), data (models), and application logic (controllers):

  • Models represent the data of the application or contain the logic for getting the data from a database.
  • Views are responsible for presenting models through the user interface.
  • Controllers handle user inputs, work with the models, and select views to display the data.

The goal of MVC is to achieve the separation of concerns between models, views, and controllers.

MVC makes it easy to add or modify views without changing the underlying models. Also, MVC allows you to write unit tests that target the model and controller without involving the UI.

Another advantage of MVC is that a model can have multiple views. And all of these views can be automatically updated based on the same model.

PyQt uses a variant of the MVC pattern by combining the view and controller of MVC into the view, which results in Model/View architecture.

The Model/View architecture allows PyQt to keep the interdependency of components to a minimum and improve reusability.

The following picture illustrates the PyQt Model/View pattern:

PyQt ModelView

In the Model/View architecture, the view handles data rendering via a delegate. A delegate has two main responsibilities:

  • Renders data.
  • Communicates with the model when data is edited.

The models, views, and delegates communicate with each other via signals and slots.

PyQt provides some standard Model/View widgets:

  • QListView – displays a list of items
  • QTableView – displays a tabular of items.
  • QTreeView – displays hierarchical data.

Besides these widgets, The QComboBox widget also supports the Model/View pattern.

In addition, PyQt has a number of base model classes such as QAbstractListModel, QAbstractTableModel, and QStandardItemModel.

PyQt Model/View example

We’ll take a simple example to illustrate the PyQt Model/View:

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QComboBox, QListView
from PyQt6.QtCore import Qt, QStringListModel


class MainWindow(QWidget):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setGeometry(100, 100, 400, 200)
        self.setWindowTitle('PyQt Model/View')

        layout = QVBoxLayout()
        self.setLayout(layout)
        
        model = QStringListModel()
        model.setStringList(['Apple','Banana','Orange'])
        
        self.list_view = QListView()
        self.list_view.setModel(model)
        
        self.combo_box = QComboBox()
        self.combo_box.setModel(model)
        
        layout.addWidget(self.combo_box) 
        layout.addWidget(self.list_view)
                       
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())
Code language: Python (python)

How it works.

In this example, we have two widgets a combobox and a list view. Both of these widgets use the same model which is an instance of the QStringListModel:

If you change an item from one widget, the other widget will update the changes automatically. In other words, you don’t need to write any code to keep all the widgets that use the same model in sync:

First, create a new instance of the QStringListModel class and set a list of strings:

model = QStringListModel()
model.setStringList(['Apple','Banana','Orange'])Code language: JavaScript (javascript)

Second, create a QListView widget and set its model to the model:

self.list_view = QListView()
self.list_view.setModel(model)Code language: PHP (php)

Third, create a QComboBox widget and set its models to the same model as the QListView widget:

self.combo_box = QComboBox()
self.combo_box.setModel(model)Code language: PHP (php)

Summary

  • PyQt uses the model/view pattern to achieve the separation of concerns.
Did you find this tutorial helpful ?