📜 ⬆️ ⬇️

Model-View in QML. Part zero, introductory

One of the most common and effective techniques for designing programs is to use the MVC programming pattern (Model-View-Controller) - Model-View-Control. MVC allows you to divide the parts of the program that are responsible for storing and accessing data, displaying data, and interacting with the user into separate weakly connected modules. This division of responsibility simplifies the structure of the program and allows you to make changes to one of these parts without affecting the rest.

This approach is actively used in Qt, and in QML it is generally the cornerstone. So, for those who study QML, understanding MVC principles is not at all superfluous.

Model-View in QML:
  1. Model-View in QML. Part zero, introductory
  2. Model-View in QML. Part One: Predefined Component Views
  3. Model-View in QML. Part Two: Custom Submissions
  4. Model-View in QML. Part Three: Models in QML and JavaScript
  5. Model-View in QML. Part Four: C ++ Models


What is MVC

Sharing responsibility is one of the fundamental principles of programming. Its essence is to divide the program into functional blocks, each of which is responsible for its part of the work. These blocks can be functions, objects, modules, etc. Blocks communicate with each other through certain interfaces. This gives some blocks independence with respect to each other and reduces the complexity of the system.
')
The basic concepts of a graphical user interface (GUI) were developed in the Xerox lab in the 70s of the twentieth century. This includes the MVC design pattern, which is designed to reduce the complexity and simplify the architecture of GUI programs using the very same division of responsibility.

So, the essence of this template is to divide the program into three components.



Schematically, the model can be represented as:



There are certain interfaces between these components that allow them to be untied. Ideally, these modules should generally be independent of each other and allow making changes or even completely replacing any module without remaking the rest.
With the development of graphical interfaces and the emergence of new types of programs, such as, for example, web applications, this separation option was not suitable everywhere. Therefore, its varieties have appeared, such as MVVC, MVP, etc. I will continue to call all varieties of this model MVC.

Quite a few modern frameworks use MVC and contain the means to separate the program in accordance with this template. Since one of the main purposes of Qt is the development of graphical user interfaces, it is also not without MVC, and Qt includes its own variation - the Model-View framework.

MVC in Qt and QML

The main idea of ​​using this template in Qt is the separation of data and their display.



Here the model is responsible for the data and access to it. Since, in the graphical interface, the same elements are often responsible for displaying elements and receiving input from the user, the idea of ​​combining presentation and control is quite logical. This is exactly what was done in Qt: the view not only displays data, but also performs control functions and is responsible for user interaction. But in order for such an association not to lose flexibility, the concept of a delegate was introduced. The delegate allows you to define how this data will be displayed and how the user can change it. The view, in essence, is now a container for delegate instances.

In QML, this principle also applies, even to a much greater degree. As I said, Model-View is one of the fundamental concepts of QML. One of the main purposes of QML is to separate the program interface into a separate part, which can be very flexible and easily adapted for different needs. For example, for a desktop application there can be one interface variant, and for a mobile one another. At the same time, the program core (model) can be written in C ++ and remain unchanged.

It is also worth noting that for some models in QML, delegates can only display data, but not edit it.
Despite the fact that the interface part is the main place for applying QML, a model on it can also be implemented, there are appropriate tools for this. If desired, the program can be done almost entirely in QML / JavaScript and keep the amount of code in C ++ to a minimum. It is with such a program that we will begin.

Simple MVC example in QML

Consider a program that displays a pair of colored rectangles with text in the middle.

import QtQuick 2.0 Rectangle { width: 360 height: 360 ListModel { id: dataModel ListElement { color: "orange" text: "first" } ListElement { color: "skyblue" text: "second" } } ListView { id: view anchors.margins: 10 anchors.fill: parent spacing: 10 model: dataModel delegate: Rectangle { width: view.width height: 100 color: model.color Text { anchors.centerIn: parent renderType: Text.NativeRendering text: model.text } } } } 

The model here is an object of type ListModel. As elements of the model, two child objects of a special type ListElement are used, in which we defined two properties: color and text.

To display, we use an object of type ListView, to which we specify the id of our object of type ListModel as a model. By itself, the view does not know which of our data to display, so you also need to give it a delegate. The delegate in QML is the type of object, an instance of which is created for each element of the model. A ListView, in turn, creates these objects, displays them in a list and provides navigation through them.

The delegate is a rectangle with the text in the middle. The color of the rectangle and the text are taken from the model. Inside the delegate all the properties of the model elements are visible. "Roles". They are available through a special model object, as well as directly, i.e. You can write just color. I prefer to write completely, so clearly, where the data comes from and there will be no conflicts if the delegate has properties with the same names.

The result of execution looks like this:



Dynamics in Model-View

In MVC, a model can be both passive and active.

Passive is a model that simply stores data and does not affect the controller and the presentation in any way. Accordingly, when changing the data in the model, she can not tell the idea about it. In this case, the controller keeps track of all changes to the model, it also tells the idea that it is necessary to update the information.

The active model can notify ideas that the data has changed. In turn, the view may display these changes. This option is considered the classic implementation of MVC.

Qt and QML use the active model. This gives us the opportunity to change the data in the model and does not worry about the display of updated data - the presentation will do everything for us.

Much refine the previous example: add a button that will add elements to the model when pressed.

 import QtQuick 2.0 Rectangle { width: 360 height: 360 ListModel { id: dataModel } Column { anchors.margins: 10 anchors.fill: parent spacing: 10 ListView { id: view width: parent.width height: parent.height - button.height - parent.spacing spacing: 10 model: dataModel clip: true delegate: Rectangle { width: view.width height: 40 color: "skyblue" Text { anchors.centerIn: parent renderType: Text.NativeRendering text: model.index } } } Rectangle { id: button width: 100 height: 40 anchors.horizontalCenter: parent.horizontalCenter border { color: "black" width: 1 } Text { anchors.centerIn: parent renderType: Text.NativeRendering text: "Add" } MouseArea { anchors.fill: parent onClicked: dataModel.append({}) } } } } 

Initially, the model does not contain any elements. When you click a button, an empty element with no properties is added to the model. The model informs you that a new item has been added. For each new item, the view creates an object, the type of which we specified as a delegate. In addition to the properties that we describe in the model elements, the delegate will have one more available - index (or model.index), containing the index of the element in the model and, accordingly, in the display. So, despite the fact that we add an empty element to the model, one property is still there and we use the index as the text.

Running the program and pressing the button we get something like this:



I showed two simple examples that illustrate the separation of melons and their display and the use of delegates to control how data is displayed. In the following text, I will refer to these two examples in order not to give their code in its entirety.

Small conclusion

Developed over 30 years ago, MVC technology has not lost its relevance. To this day, it is the basis for designing programs with a graphical interface; Now it is difficult to imagine such a program that does not use MVC.
As a technology developed for creating graphical interfaces, Qt and, especially, QML have full MVC support. The necessary tools are part of the libraries, moreover, in Qt itself, the ideology of this template is quite clearly visible.
Accordingly, the use of MVC here is natural and that is how the developers intended it, and it was with this vision that the framework was designed.

At this introductory part can be considered complete, and in the next article we will take a closer look at the presentation.

Source: https://habr.com/ru/post/181712/


All Articles