Quite often, the same question arises on the forum regarding the problem of displaying content embedded in any QML objects.
The most common manifestation of this problem is when ListView content scrolls beyond its scope. In any case, this is one of those frequent cases when beginners encounter this problem when starting to learn QML. Well, or another option when faced with such a problem when using Rectangle objects.
In the following image below, you can see two application windows that illustrate this problem.
- The left window shows what the layout looks like initially
- The right window shows that if you start scrolling through ListView content, it will go under the Title text, although it should have been cropped.
Initial code example
This is what the original program code looks like.
import QtQuick 2.12 import QtQuick.Window 2.12 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") Text { id: topText text: qsTr("Title") anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top } ListView { width: 180; height: 200 model: contactModel delegate: Text { text: name + ": " + number } anchors.horizontalCenter: parent.horizontalCenter anchors.top: topText.bottom } ListModel { id: contactModel ListElement { name: "Bill Smith" number: "555 3264" } ListElement { name: "John Brown" number: "555 8426" } ListElement { name: "Sam Wise" number: "555 0473" } } }
To solve this problem, just set the clip: true property of ListView .
ListView { clip: true /* код */ }
And now ListView content will not go beyond ListView
Using Rectangle Objects
Similarly, clip works for Rectangle objects. Here is the program code, as well as an example before and after including clip.
import QtQuick 2.12 import QtQuick.Window 2.12 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") Rectangle { x: 27 y: 31 width: 100 height: 100 color: "blue" clip: true Rectangle { x: -20 y: -20 width: 100 height: 100 color: "green" } } }
Rounding
But what does not work when using clip is rounding, even if you adjust the radius of rounding at the parent Rectangle object.
For example, here we have such a code will not give the expected result
import QtQuick 2.12 import QtQuick.Window 2.12 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") Rectangle { x: 27 y: 31 width: 100 height: 100 color: "blue" radius: 30 // set rounding clip: true // enable cropping Rectangle { x: -20 y: -20 width: 100 height: 100 color: "green" } } }
The result
This clip behavior is standard and has been done for performance reasons, since almost all QML graphic elements are inherited from the Item type. This means that additional processing of masks throughout the application is redundant.
But the expected result can be achieved with the following program code using the graft effect OpacityMask
import QtQuick 2.12 import QtQuick.Window 2.12 import QtGraphicalEffects 1.13 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") Rectangle { id: rect x: 27 y: 31 width: 100 height: 100 color: "blue" layer.enabled: true layer.effect: OpacityMask { maskSource: Item { width: rect.width height: rect.height Rectangle { anchors.centerIn: parent width: rect.adapt ? rect.width : Math.min(rect.width, rect.height) height: rect.adapt ? rect.height : width radius: 30 } } } Rectangle { x: -20 y: -20 width: 100 height: 100 color: "green" } } }
And the result will be as follows
Conclusion
In conclusion, I’ll say that clip is a very useful property, which for performance reasons was set to false by default. At the same time, this property performs only simple cropping in the form of a rectangle, and something more complex needs to be cropped using a mask.
Зачем внутри OpacityMask Item, почему сразу Rectangle не вставить?
И что за rect.adapt?
Мое предложение: