Qt QML SwipeView с фоном, как я могу размыть правую область при перемещении страницы?

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

Я нашел этот фрагмент в конце этой беседы, который побудил меня использовать белый прямоугольник в сочетании с полупрозрачным FastBlur, сэмплирующим фон: https://forum.qt.io/topic/38297/a-полупрозрачный-прямоугольник-который-также-размывает/7

Rectangle {
    anchors.fill: fastBlur
    color: "white"
}

FastBlur {
    id: fastBlur

    height: 124

    width: parent.width
    radius: 40
    opacity: 0.55

    source: ShaderEffectSource {
        sourceItem: flickable
        sourceRect: Qt.rect(0, 0, fastBlur.width, fastBlur.height)
    }
}

Когда я перехожу на следующую страницу в SwipeView, фон остается статичным, но размытие, конечно же, не происходит, потому что область sourceRect не перемещается относительно своего родителя, просто родитель перемещается относительно фона. Размытие по-прежнему отбирает фон из исходного положения, а не из нового положения, когда он перемещается через обзор.

Итак, я понял, что могу получить SwipeView.contentItem.contentX (благодаря ответу на QML: позиция элемента в SwipeView по середине!) Но на обеих моих страницах я должен по-разному учитывать contentX в зависимости от того, в каком порядке они расположены

Я создал здесь пример проекта размытия, чтобы показать, что я имею в виду. https://github.com/ftab/BlurTest

В частности, в sourceRect - https://github.com/ftab/BlurTest/blob/master/Page1Form.qml#L23

sourceRect: Qt.rect(
                fastBlur.x - swipeView.contentItem.contentX,
                fastBlur.y,
                fastBlur.width,
                fastBlur.height)

Это дает желаемый эффект обновления размытия при перемещении по фону, но работает только потому, что размытая область находится на первой странице просмотра смахивания, а contentX изменяется от 0 до 640. Если бы это было на второй странице, я ' Мне нужно было сделать 640 - contentX + fastBlur.x, а затем, если я снова его перемещу, мне придется снова его настроить и т. д.

Есть ли лучший способ сделать это, или я в значительной степени застрял в редактировании sourceRect всякий раз, когда добавляю новую страницу или меняю порядок?

edit: полный файл QML с 3 страницами, например:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
import QtGraphicalEffects 1.0

ApplicationWindow {
    visible: true
    width: 640
    height: 480

    SwipeView {
        id: swipeView
        anchors.fill: parent
        currentIndex: tabBar.currentIndex
        background: Image {
            id: imgBackground
            anchors.fill: parent
            fillMode: Image.PreserveAspectCrop
            source: "nature_1.jpg"
        }

        Item {
            id: item1

            Rectangle {
                id: recFrost
                anchors.fill: fastBlur
                color: "white"
            }
            FastBlur {
                id: fastBlur
                anchors.fill: recControls
                source: ShaderEffectSource {
                    sourceItem: imgBackground

                    sourceRect: Qt.rect(
                                    fastBlur.x - swipeView.contentItem.contentX,
                                    fastBlur.y,
                                    fastBlur.width,
                                    fastBlur.height)
                }
                radius: 32
                opacity: 0.55
            }
            Rectangle {
                id: recControls
                width: 364
                height: 89
                color: "#00000000"
                anchors.bottomMargin: 8
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.bottom: parent.bottom

                Label {
                    text: qsTr("First page")
                    anchors.centerIn: parent
                }
            }
        }

        Item {
            id: item2

            Rectangle {
                id: recFrost2
                anchors.fill: fastBlur2
                color: "white"
            }
            FastBlur {
                id: fastBlur2
                anchors.fill: recControls2
                source: ShaderEffectSource {
                    sourceItem: imgBackground

                    sourceRect: Qt.rect(
                                    swipeView.width - swipeView.contentItem.contentX + fastBlur2.x,
                                    fastBlur2.y,
                                    fastBlur2.width,
                                    fastBlur2.height)
                }
                radius: 32
                opacity: 0.55
            }
            Rectangle {
                id: recControls2
                width: 364
                height: 89
                color: "#00000000"
                anchors.centerIn: parent

                Label {
                    text: qsTr("Second page")
                    anchors.centerIn: parent
                }
            }
        }

        Item {
            id: item3

            Rectangle {
                id: recFrost3
                anchors.fill: fastBlur3
                color: "white"
            }
            FastBlur {
                id: fastBlur3
                anchors.fill: recControls3
                source: ShaderEffectSource {
                    sourceItem: imgBackground

                    sourceRect: Qt.rect(
                                    swipeView.width * 2 - swipeView.contentItem.contentX + fastBlur2.x,
                                    fastBlur3.y,
                                    fastBlur3.width,
                                    fastBlur3.height)
                }
                radius: 32
                opacity: 0.55
            }
            Rectangle {
                id: recControls3
                width: 364
                height: 89
                color: "#00000000"
                anchors.topMargin: 8
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.top: parent.top

                Label {
                    text: qsTr("Third page")
                    anchors.centerIn: parent
                }
            }
        }
    }

    footer: TabBar {
        id: tabBar
        currentIndex: swipeView.currentIndex
        TabButton {
            text: qsTr("First")
        }
        TabButton {
            text: qsTr("Second")
        }
        TabButton {
            text: qsTr("Third")
        }
    }
}

person fury    schedule 09.06.2017    source источник
comment
Я не могу представить, что вы хотите, так как не могу запустить ваш код. Я не хочу переходить по каким-либо ссылкам, чтобы ответить на ваш вопрос, поскольку это означает, что как только ссылки перестают работать, вопрос становится бесполезным для других. Включите в этот вопрос все, что требуется для минимального, полного и поддающегося проверке примера.   -  person derM    schedule 09.06.2017
comment
@derM добавил полный файл QML, извините за то, что   -  person fury    schedule 09.06.2017


Ответы (1)


Вместо того, чтобы делать это с шагом swipeView.width, вы можете использовать x позицию родительской страницы в SwipeView:

sourceRect: Qt.rect(fastBlur2.x - swipeView.contentItem.contentX + item2.x,
                    fastBlur2.y,
                    fastBlur2.width,
                    astBlur2.height)

В качестве альтернативы вы можете использовать mapToItem() Item. Однако, поскольку mapToItem - это функция, использование ее возвращаемого значения не приведет к запуску обновлений привязки, когда один элемент перемещается относительно другого, нам придется мягко намекнуть механизму QML, когда следует повторно оценивать привязку.

sourceRect: {
    swipeView.contentItem.contentX; /*here we access contentX in order to
    force the reevaluation of the entire expression when contentX changes.*/
    return fastBlur3.mapToItem(swipeView, 0, 0, fastBlur3.width, fastBlur3.height);
}
person GrecKo    schedule 09.06.2017
comment
fastBlur2.x - swipeView.contentItem.contentX + fastBlur2.parent.x, - person fury; 12.06.2017