albertaloop / T_SWE_2022_2023

Software for AlbertaLoop's first-generation pod.
MIT License
3 stars 0 forks source link

Model/View Programming with QTableView and QAbstractTableModel #13

Closed Iyury1 closed 1 year ago

Iyury1 commented 2 years ago

Summary

Our UI will contain several tables that need to be refreshed with data. To do so, we could use a QTableWidget or QTableView. A widget is a standard UI element. A View is like a widget but allows for more flexibility in how data can be presented. For our PacketLogger table we may have a very large number of packets to display. To speed up the PacketLogger table, we could include functionality to reduce the number of elements displayed at a time. This would require using QTableView over the QTableWidget.

Another benefit to using Views is that they conform to a Model-View architecture when combined with Model classes. This is a method of separating UI objects from the data being displayed. The data we want to be displayed in a table could exist in a class that is derived from a QT Model class (QAbstractItemModel). The Model class could then be attached to the TableView, and the data could automatically be updated into the TableView.

These concepts are explained in the official QT docs: https://doc.qt.io/qt-5/model-view-programming.html#introduction-to-model-view-programming https://doc.qt.io/qt-5/model-view-programming.html#using-models-and-views https://doc.qt.io/qt-5/model-view-programming.html#model-classes https://doc.qt.io/qt-5/model-view-programming.html#view-classes

Since Model classes represent data in rows and columns that can be indexed, there could be a direct mapping from the indexes assigned to our data and the order it is displayed in the TableView. Rather than subclass from QAbstractItemModel, we could use QAbstractTableModel which has already implemented some of the required functions.

The PyQT5 QAbstractTableModel docs explain we must implement the functions rowCount(), columnCount(), and data() in our subclass. Our custom model class will contain our data, and return the values in the data() function as indicated by an index provided. https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtcore/qabstracttablemodel.html#

We can attach our Model class to the TableView by calling setModel() on the TableView. The TableView will then use the data() function we defined to populate the View with the data from our Model.

Here is an example of creating a custom model from QAbstractListModel and attaching it to a QListView in PyQT5: https://www.pythonguis.com/tutorials/modelview-architecture/

Acceptance Criteria

Iyury1 commented 1 year ago

I created an example project at this branch: https://github.com/albertaloop/T_SWE_2022_2023/tree/GUI/qt-modelview/GUI/TableView-example

The file "main.py" creates a Window containing a TableView and a Button. The TableView has its model set to "TableModel" which inherits from QAbstractTableModel. The TableView gets initialized with some default values set in the TableModel constructor, and an example of updating a value is included in the "incrementCell()" method which is called when the button is pressed.