Досить часто на форумі виникає одне і те ж питання, який стосується проблеми відображення контенту, вкладеного в будь-які об'єкти QML.
Найбільш частим проявом цієї проблеми є ситуація, коли контент ListView при прокручуванні виходить за його межі. У всякому разі це один з тих частих випадків, коли новачки стикаються з цією проблемою, починаючи вивчати QML. Ну або ще один варіант, коли стикаються з такою проблемою при використання об'єктів Rectangle.
На нижче наступному зображенні ви можете побачити два вікна програми, які ілюструють цю проблему.
- Ліве вікно показує, як виглядає верстка спочатку
- Права вікно показує, що якщо почати гортати контент ListView, то він буде заходити під текст Title, хоча мав би обрізатися.
Початковий приклад коду
Ось так виглядає початковий програмний код.
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" } } }
Щоб вирішити дану проблему, досить встановити властивість clip: true у ListView .
ListView { clip: true /* код */ }
І тепер контент ListView не виходитиме за межі ListView
Використання у Rectangle об'єктів
Аналогічним чином clip працює і для Rectangle об'єктів Ось програмний код, а також приклад до і після включення 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"https://evileg.com/ru/knowledge/article/577/change/# clip: true Rectangle { x: -20 y: -20 width: 100 height: 100 color: "green" } } }
Закруглення країв
А ось, що не працює при використанні clip, так це закруглення країв, навіть якщо налаштовуватися радіус закруглення країв у батьківського Rectangle об'єкта.
Наприклад у нас ось такий код не дасть очікуваного результату
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 // встановили закруглення clip: true // включили обрізку Rectangle { x: -20 y: -20 width: 100 height: 100 color: "green" } } }
Отриманний результат
Така поведінка clip є стандартним і зроблено було так з міркувань продуктивності, оскільки практично всі графічні елементи QML успадковуються від типу Item. А значить додаткова обробка масок у всьому додатку є надмірною.
За очікуваного результату можна досягти наступним програмним кодом за допомогою граффтческого ефекту 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" } } }
А результат буде таким
Висновок
В якості висновку скажу, що clip - це дуже корисна властивість, яке з міркувань продуктивності за замовчуванням встановили в false. При цьому дане властивість виконує тільки просту обрізку в вигляді прямокутника, а щось більш складне потрібно обрізати за допомогою маски.
Зачем внутри OpacityMask Item, почему сразу Rectangle не вставить?
И что за rect.adapt?
Мое предложение: