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