Обрезка движущегося прямоугольника в пределах скругленного прямоугольника в QML

Я создаю собственный стиль в QML и хотел бы иметь неопределенный индикатор выполнения, который выглядит следующим образом: закругленный фон с закругленной полосой внутри, которая перемещается слева направо.

У меня проблема с поведением, когда полоска доходит до конца. Использование только свойства clip приводит к тому, что закругленный стержень становится квадратным при контакте с краем.

Rectangle {
    id: bg
    color: "black"
    width: 120; height: 8; radius: 4; x: 100; y: 50
    clip: true
    
    Rectangle {
        id: bar
        color: "orange"
        width: 60; height: 8; radius: 4
      
        NumberAnimation on x {
            running: true
            from: -(bar.width * 1.2 )
            to: bg.width * 1.2
            loops: Animation.Infinite
            duration: 1000
        } 
    }
}

Это связано с тем, что clip использует ограничивающий прямоугольник родительского объекта. Справедливо.

Затем я попытался использовать MultiEffect (я использую Qt6, поэтому нет OpacityMask) для применения к панели, однако после некоторых экспериментов я обнаружил, что свойства маскировки MultiEffect не учитывают положение MaskSource, поэтому это не сработало. работа.

MultiEffect {
    source: bar
    anchors.fill: bar
    maskEnabled: true
    maskSource: bg
}

Как мне добиться желаемого поведения, т. е. обрезать полосу фоном с закругленными углами?

Я знаю, что могу добиться аналогичного эффекта, увеличивая и уменьшая ширину полосы на соответствующих краях, но я хотел бы избежать этого, если это возможно.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
84
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, в Qt6 есть OpacityMask, но он находится под Qt5Compat.GraphicalEffects.

Второй момент: проблема решаема с помощью Qt6 MultiEffect. Проблема в том, что maskSource должен быть указан немного иначе, чем эквивалент OpacityMask, с необходимым Item для создания слоев.

Анимацию bar необходимо обновить, чтобы она содержала как черный фон, так и панель анимации.

[РЕДАКТИРОВАТЬ]

Для улучшения сглаживания давайте поместим (1) включим клип и радиус в source, (2) однако выключим сглаживание в maskSource.

    Rectangle {
        id: barWithBackground
        width: 120; height: 8; x: 100; y: 50; radius: 4
        clip: true
        visible: false
        color: "black"
        Rectangle {
            id: bar
            color: "orange"
            width: 60; height: 8; radius: 4
            NumberAnimation on x {
                running: true
                from: -(bar.width * 1.2 )
                to: barWithBackground.width * 1.2
                loops: Animation.Infinite
                duration: 1000
            }
        }
    }

    // OpacityMask
    // Qt5.* from QtGraphicalEffects
    // Qt6.* from Qt5Compat.GraphicalEffects
    // OpacityMask {
    //     source: barWithBackground
    //     anchors.fill: barWithBackground
    //     maskSource: roundedRectangleMask
    // }

    // Since Qt6.5
    MultiEffect {
        source: barWithBackground
        anchors.fill: barWithBackground
        maskEnabled: true
        maskSource: roundedRectangleMask
    }

    Item {
        id: roundedRectangleMask
        width: 120; height: 8
        layer.enabled: true
        visible: false
        Rectangle {
            color: "black"
            width: 120; height: 8; radius: 4
            antialiasing: false
        }
    }

Великолепно, это сработало (с некоторыми изменениями, я отредактирую, когда очередь редактирования иссякнет). Похоже, что это полностью отключило сглаживание для затронутых объектов. Знаете ли вы, как его снова включить? Я не смог найти это путем быстрого поиска в Google

eejakobowski 20.05.2024 08:09

@eejakobowski Я включил сглаживание в source и отключил сглаживание в maskSource. Думаю, это улучшит результат.

Stephen Quan 20.05.2024 11:13

Другие вопросы по теме