SwipeView with dynamic "interactive" breaks "currentIndex" binding
-
wrote on 12 Dec 2019, 09:01 last edited by
Hi,
I'm trying to create a SwipeView where the first page has the
interactive
property false, while the others have it enabled. The effect that I'm trying to achieve is to have the main page with a link to the others, but the others can only go back to the main page (like the iOS settings menu).The issue is that after the first change page, the
currentIndex
property loses binding causing the SwipeView to break.Here's the application output:
qrc:/main.qml:10:5: QML SwipeView: Binding loop detected for property "currentIndex" file:///home/rcc/Qt/5.12.6/gcc_64/qml/QtQuick/Controls.2/SwipeView.qml:49:18: QML ListView: Binding loop detected for property "currentIndex"
and here's the default swipe view application (QtCreator -> New Project -> Qt Quick Application - Swipe)
main.qml
:import QtQuick 2.12 import QtQuick.Controls 2.5 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Tabs") SwipeView { id: swipeView anchors.fill: parent currentIndex: tabBar.currentIndex interactive: false onCurrentIndexChanged: { if (currentIndex === 0) { interactive = false } else { interactive = true } } Page1Form {} Page2Form {} } footer: TabBar { id: tabBar currentIndex: swipeView.currentIndex TabButton { text: qsTr("Page 1") } TabButton { text: qsTr("Page 2") } } }
To reproduce the bug:
- Click on Page 2.
- Swipe left.
- Click again on Page 2.
Any suggestions to solve this issue?
-
wrote on 12 Dec 2019, 09:14 last edited by
You have binding loop, as output says. You need to remove
currentIndex: tabBar.currentIndex
binding from yourSwipeView
and control its index by clicking on tab button, like this:SwipeView { id: swipeView anchors.fill: parent interactive: currentIndex Rectangle {color: "red"; opacity: 0.5} Rectangle {color: "green"; opacity: 0.5} Rectangle {color: "blue"; opacity: 0.5} } footer: TabBar { id: tabBar currentIndex: swipeView.currentIndex TabButton { text: qsTr("Page 1") onClicked: swipeView.setCurrentIndex(TabBar.index) } TabButton { text: qsTr("Page 2") onClicked: swipeView.setCurrentIndex(TabBar.index) } }
-
You have binding loop, as output says. You need to remove
currentIndex: tabBar.currentIndex
binding from yourSwipeView
and control its index by clicking on tab button, like this:SwipeView { id: swipeView anchors.fill: parent interactive: currentIndex Rectangle {color: "red"; opacity: 0.5} Rectangle {color: "green"; opacity: 0.5} Rectangle {color: "blue"; opacity: 0.5} } footer: TabBar { id: tabBar currentIndex: swipeView.currentIndex TabButton { text: qsTr("Page 1") onClicked: swipeView.setCurrentIndex(TabBar.index) } TabButton { text: qsTr("Page 2") onClicked: swipeView.setCurrentIndex(TabBar.index) } }
wrote on 12 Dec 2019, 11:10 last edited by@IntruderExcluder said in SwipeView with dynamic "interactive" breaks "currentIndex" binding:
You have binding loop, as output says. You need to remove
currentIndex: tabBar.currentIndex
binding from yourSwipeView
and control its index by clicking on tab button, like this:SwipeView { id: swipeView anchors.fill: parent interactive: currentIndex Rectangle {color: "red"; opacity: 0.5} Rectangle {color: "green"; opacity: 0.5} Rectangle {color: "blue"; opacity: 0.5} } footer: TabBar { id: tabBar currentIndex: swipeView.currentIndex TabButton { text: qsTr("Page 1") onClicked: swipeView.setCurrentIndex(TabBar.index) } TabButton { text: qsTr("Page 2") onClicked: swipeView.setCurrentIndex(TabBar.index) } }
I've done what you say, but the problem is still here:
import QtQuick 2.12 import QtQuick.Controls 2.5 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Tabs") SwipeView { id: swipeView anchors.fill: parent interactive: currentIndex Rectangle { color: "red" opacity: 0.5 } Rectangle { color: "green" opacity: 0.5 } Rectangle { color: "blue" opacity: 0.5 } } footer: TabBar { id: tabBar currentIndex: swipeView.currentIndex TabButton { text: qsTr("Page 1") onClicked: swipeView.setCurrentIndex(TabBar.index) } TabButton { text: qsTr("Page 2") onClicked: swipeView.setCurrentIndex(TabBar.index) } } }
Error:
file:///home/rcc/Qt/5.12.6/gcc_64/qml/QtQuick/Controls.2/SwipeView.qml:49:18: QML ListView: Binding loop detected for property "currentIndex"
By the way, I'm using Qt 5.12.6 Linux desktop.
-
wrote on 13 Dec 2019, 13:48 last edited by
I'm linking the StackOverflow question and the Qt Bug
This is the workaround suggested:
onCurrentIndexChanged: { if (currentIndex === 0) { Qt.callLater(function() { interactive = false }) } else { Qt.callLater(function() { interactive = true }) } }
4/4