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

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

Я нашел этот фрагмент в конце этой цепочки, который побудил меня использовать белый прямоугольник в сочетании с полупрозрачным FastBlur для выборки фона: https://forum.qt.io/topic/38297/a-semi-transparent-rectangle-that-also-blurs/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 всякий раз, когда я добавляю другую страницу или меняю порядок?

редактировать: полный файл 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")
        }
    }
}

1 ответ

Решение

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

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

В качестве альтернативы вы могли бы Item"s mapToItem(), Тем не менее, так как 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);
}
Другие вопросы по тегам