转到特定页面后如何将SwipeView的currentIndex设置为TabBar的currentIndex "by reference"?

How to set currentIndex of SwipeView to currentIndex of TabBar "by reference" after going to specific page?

我正在开始使用 QtQuick Controls 2.0。我有 C++ 经验和少量 Qt 经验,但我以前没有使用过 QML。

我有一个 TabBar 和一个 SwipeView,它们相互 link。我的意思是,当您 select TabBar 上的某个页面时,SwipeView 会转到该页面。当您从 SwipeView 滑动到某个页面时,TabBar 会自行更新以反映这一点。

作为学习练习,我决定创建一个将用户转到第二页的按钮。问题是我似乎无法找到一种方法来做到这一点而不弄乱 TabBarSwipeView 之间的 link。

下面的代码是我想出的最好的代码。它正确地转到第二页,当我用 TabBar 更改当前页面时,SwipeView 仍然更新。但是,滑动 到新页面不再更新 TabBar。似乎将 tabBar.currentIndex 设置为 swipeView.currentIndex 仅在使用冒号初始化时才具有通过引用设置的效果。使用等号按值设置。我怎样才能移动到特定页面,同时仍然保持不变 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")
        }
    }
}

C++ 代码只是 Qt Creator 为我提供的默认代码:

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

您可能正在寻找 Signals。来自 Qt 文档:

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.

因此,对于您的示例:

SwipeView {
    id: swipeView
    ...
    currentIndex: tabBar.currentIndex
    onCurrentIndexChanged: {
        tabBar.currentIndex = currentIndex
    }
...
footer: TabBar {
    id: tabBar
    currentIndex: swipeView.currentIndex
    onCurrentIndexChanged: {
        swipeView.currentIndex = currentIndex
    }
    ...

这样你就可以简单地设置其中一个的 currentIndex 并放心,由于信号处理程序,它们将保持 "linked"。

编辑:

,你也可以像这样使用Qt.binding

onClicked: {
    swipeView.currentIndex = 1;
    swipeView.currentIndex = Qt.binding(function() {return tabBar.currentIndex})
}

这将在分配静态值后恢复绑定。

为了在不破坏 currentIndex 绑定的情况下移动到下一页或上一页,您可以分别调用 incrementCurrentIndex() or decrementCurrentIndex()。这些方法在 Qt 5.8 中的 Qt Quick Controls 2.1 中引入。

鉴于 currentIndex setter 又名。 QQuickContainer::setCurrentIndex()是一个slot,也可以从QML中调用setCurrentIndex()跳转到任意页面。这也不会破坏现有的绑定。

Button {
    onClicked: tabBar.setCurrentIndex(1)
}