QML - Урок 038. Использование свойства clip для обрезки child объектов внутри Item или Rectangle

clip, OpacityMask, ListView, QML

Содержание

Довольно часто на форуме возникает один и тот же вопрос, который касается проблемы отображения контента, вложенного в какие-либо объекты 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. При этом данное свойство выполняет только простую обрезку в виде прямоугольника, а что-то более сложное нужно обрезать с помощью маски.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
- блог компании
Поддержать автора Donate

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Donate

Здравствуйте, уважаемые пользователи EVILEG !!!

Если сайт вам помог, то поддержите разработку сайта финансово, пожалуйста.

Вы можете сделать это следующими способами:

Спасибо, Евгений Легоцкой

DK
1 апреля 2020 г. 8:03
Dmitry Kozhinov

C++ - Тест 001. Первая программа и типы данных

  • Результат:40баллов,
  • Очки рейтинга-8
A
30 марта 2020 г. 12:47
Anna

C++ - Тест 001. Первая программа и типы данных

  • Результат:60баллов,
  • Очки рейтинга-1
A
29 марта 2020 г. 12:14
Alexanderv66

C++ - Тест 003. Условия и циклы

  • Результат:71баллов,
  • Очки рейтинга1
Последние комментарии
3 апреля 2020 г. 8:06
Konstantin Grudnitskiy

Я надеюсь вы уже разобрались в чем дело, но если вдруг нет, то проблема состоит в том, что вы пытаетесь запустить программу из интерпретатора питона. Файл main.py это уже готова…
3 апреля 2020 г. 6:18
Konstantin Grudnitskiy

>>> text = 'hello world'>>> ' '.join(word for word in text.split()[:-1])'hello'>>> def remove_last_word(text):... return text and ' '.join(word for word in text.s…
27 марта 2020 г. 14:40
Евгений Легоцкой

Добрый день. В конце пятой статьи скачать можете.
27 марта 2020 г. 14:28
mkdir _

Здравствуйте, а можно, пожалуйста, ссылку на целые исходники, если есть?
27 марта 2020 г. 4:36
Евгений Легоцкой

Скорее всего также, как и для установки всех остальных переменых в CMake, через использование set
Сейчас обсуждают на форуме
3 апреля 2020 г. 12:53
BlinCT

Само собою на компе этого незаметно.
3 апреля 2020 г. 8:48
Intruder

Евгений, добрый день. Спасибо!
s
3 апреля 2020 г. 7:52
solmik

да вроде много чего установленно, если неправильный путь указать то же самое, пробовал запустить видео через плей лист (по примерам из док)и из него назад путь взять, не получилось
3 апреля 2020 г. 5:50
Юрий-В

Спасибо ! Поковырявшись и посмотрев интерфейс QSvgRender и т.д. понимаю что похоже нужно будет лезть в реализацию ::render(..). Кто может подсказать как и где выкачать актуальные исходники…
2 апреля 2020 г. 2:46
Евгений Легоцкой

Я думаю, что это где-то описано, но в такой глубине документации и максимум в самых базовых вещах, то есть отдельно в классах этого не пишут, просто потому, что придётся писать для каждого класс…
EVILEG
О нас
Услуги
© EVILEG 2015-2019
Рекомендует хостинг TIMEWEB