转到特定页面后,如何“通过引用”将 SwipeView 的 currentIndex 设置为 TabBar 的 currentIndex?

Posted

技术标签:

【中文标题】转到特定页面后,如何“通过引用”将 SwipeView 的 currentIndex 设置为 TabBar 的 currentIndex?【英文标题】:How to set currentIndex of SwipeView to currentIndex of TabBar "by reference" after going to specific page? 【发布时间】:2017-04-24 00:27:30 【问题描述】:

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

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

作为学习练习,我决定创建一个按钮,将用户引导至第二页。问题是,我似乎无法找到一种方法来不搞乱TabBarSwipeView 之间的链接。

以下代码是我想出的最好的。它正确地转到第二页,当我用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();

【问题讨论】:

【参考方案1】:

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

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

Button 
    onClicked: tabBar.setCurrentIndex(1)

【讨论】:

谢谢。例如,在想要转到第 20 页的情况下,是否最好简单地使用 for 循环和一些基于 currentIndex 的数学来到达正确的页面,或者最好像我一样做在我的回答中做了吗? 跳转到任意页面确实需要更复杂的解决方案。它可以是双向信号处理程序,也可以使用Qt.binding() 来恢复绑定。这个讨论让我意识到我们可以简单地允许从 QML 调用setCurrentIndex() 原来setCurrentIndex()实际上是一个槽,所以你已经可以从QML调用它而不会破坏绑定。我们会将其添加到文档中以使其正式化。 这就是我正在寻找的简单解决方案!谢谢;)【参考方案2】:

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

属性更改信号处理程序

当 QML 属性的值出现时,会自动发出信号 变化。这类信号是属性变化信号和信号 这些信号的处理程序以 onChanged 的形式编写 其中 是属性的名称,带有第一个字母 大写。

因此,对于您的示例:

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

这样您就可以简单地设置任何一个的 currentIndex 并放心,由于信号处理程序,它们将保持“链接”。

编辑:

As pointed out by jpnurmi,你也可以像这样使用Qt.binding

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

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

【讨论】:

以上是关于转到特定页面后,如何“通过引用”将 SwipeView 的 currentIndex 设置为 TabBar 的 currentIndex?的主要内容,如果未能解决你的问题,请参考以下文章

a标记 跳转到 另一页面特定位置

如何使用 UIPageViewController 跳转到特定页面?

Qt/QML:在加载程序加载后访问 ListView 以跳转到特定项目/页面

如何转到页面上的特定元素? [复制]

如何跳转到 UIPageViewController 中的特定页面,setViewControllers 不起作用

如何使用 Objective-C 使用 VFR pdf 阅读器库转到特定页面