Qt QML SwipeView带背景,如何在页面移动时模糊正确的区域?

时间:2017-06-09 06:22:46

标签: qt qml blur swipeview qtquickcontrols2

我有一张带有背景图片的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: Mid-swipe position of item in SwipeView的答案!)但是在我的两个页面中,我必须根据内容对内容X进行不同的说明他们订购

我在这里设置了一个示例模糊项目,以显示我的意思。 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?

编辑:完成3页的QML文件,例如:

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 个答案:

答案 0 :(得分:2)

您可以在swipeView.width中使用父页面的x位置,而不是以SwipeView为增量进行操作:

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

或者您可以Item mapToItem()。 但是,由于mapToItem是一个函数,当一个项相对于另一个项移动时,使用它的返回值不会触发绑定更新,我们必须轻轻提示QML引擎何时重新评估绑定。 / p>

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);
}