I'm getting started with QtQuick Controls 2.0. I have experience with C++ and a small amount of experience with Qt, but I have not worked with QML before.
I have a TabBar
and a SwipeView
that are linked to each other. What I mean by this is that when you select a page on the TabBar
, the SwipeView
goes to that page. When you swipe to a page from the SwipeView
, the TabBar
updates itself to reflect that.
As a learning exercise, I decided to create a button that would send the user to the second page. The issue is that I can't seem to find a way to do so without messing up the link between the TabBar
and the SwipeView
.
The following code is the best I've come up with. It correctly goes to the second page, and when I change the current page with the TabBar
the SwipeView
still updates. However, swiping to a new page no longer updates the TabBar
. It appears that setting tabBar.currentIndex
to swipeView.currentIndex
only has the effect of setting by reference when done with the colon to initialize. Doing so with an equals sign sets by value. How can I move to a specific page while still maintaining the invariant that swipeView.currentIndex == tabBar.currentIndex
?
// main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex
Page {
Button {
text: qsTr("Continue to Page 2")
onClicked: {
tabBar.currentIndex = 1;
// this next line merely sets tabBar.currentIndex to 1
tabBar.currentIndex = swipeView.currentIndex
}
anchors.centerIn: parent
width: text.implicitWidth
height: text.implicitHeight
}
}
Page {
Label {
text: qsTr("Second page")
anchors.centerIn: parent
}
}
}
footer: TabBar {
id: tabBar
currentIndex: swipeView.currentIndex
TabButton {
text: qsTr("First")
}
TabButton {
text: qsTr( "Second")
}
}
}
The C++ code is simply the default that Qt Creator provided for me:
// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
}
In order to move to the next or the previous page without breaking the currentIndex
bindings, you can call incrementCurrentIndex()
or decrementCurrentIndex()
, respectively. These methods were introduced in Qt Quick Controls 2.1 in Qt 5.8.
Given that the currentIndex
setter aka. QQuickContainer::setCurrentIndex()
is a slot, you can also call setCurrentIndex()
from QML to jump to an arbitrary page. This will not break the existing bindings either.
Button {
onClicked: tabBar.setCurrentIndex(1)
}
You could be looking for Signals. From the Qt documentation:
Property Change Signal Handlers
A signal is automatically emitted when the value of a QML property changes. This type of signal is a property change signal and signal handlers for these signals are written in the form on<Property>Changed where <Property> is the name of the property, with the first letter capitalized.
Thus, for your example:
SwipeView {
id: swipeView
...
currentIndex: tabBar.currentIndex
onCurrentIndexChanged: {
tabBar.currentIndex = currentIndex
}
...
footer: TabBar {
id: tabBar
currentIndex: swipeView.currentIndex
onCurrentIndexChanged: {
swipeView.currentIndex = currentIndex
}
...
And that way you can simply set the currentIndex of either and rest assured that they will remain "linked" due to the signal handlers.
As pointed out by jpnurmi, you can also use Qt.binding
like so:
onClicked: {
swipeView.currentIndex = 1;
swipeView.currentIndex = Qt.binding(function() {return tabBar.currentIndex})
}
This will restore the binding after the static value has been assigned.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With