Как установить currentIndex для SwipeView на currentIndex для TabBar по ссылке после перехода на определенную страницу?

Я начинаю работать с QtQuick Controls 2.0. У меня есть опыт работы с C ++ и небольшой опыт работы с Qt, но раньше я не работал с QML.

У меня есть TabBar и SwipeView, которые связаны друг с другом. Я имею в виду, что когда вы выбираете страницу на TabBar, SwipeView переходит на эту страницу. Когда вы переходите к странице из SwipeView, TabBar обновляется, чтобы отразить это.

В качестве обучающего упражнения я решил создать кнопку, которая отправляла бы пользователя на вторую страницу. Проблема в том, что я не могу найти способ сделать это, не нарушив связь между TabBar и SwipeView.

Следующий код - лучшее, что я придумал. Он правильно переходит на вторую страницу, и когда я меняю текущую страницу с 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();
}

person Jon McClung    schedule 24.04.2017    source источник


Ответы (2)


Чтобы перейти к следующей или предыдущей странице, не нарушая привязки currentIndex, вы можете вызвать _ 2_ или _ 3_ соответственно. Эти методы были представлены в Qt Quick Controls 2.1 в Qt 5.8.

Учитывая, что сеттер currentIndex aka. QQuickContainer::setCurrentIndex() - это слот, вы также можете вызвать setCurrentIndex() из QML, чтобы перейти на произвольную страницу. Это также не нарушит существующие привязки.

Button {
    onClicked: tabBar.setCurrentIndex(1)
}
person jpnurmi    schedule 24.04.2017
comment
Спасибо. В случае, например, если вы хотите перейти на страницу 20, было бы предпочтительнее просто использовать цикл for и некоторую математику, основанную на currentIndex, чтобы перейти на нужную страницу, или было бы лучше сделать это, как я сделал в мой ответ? - person Jon McClung; 24.04.2017
comment
Действительно, переход на произвольную страницу требует более сложного решения. Это могут быть двусторонние обработчики сигналов или использование Qt.binding() для восстановления привязок. Это обсуждение заставляет меня понять, что мы могли бы просто разрешить вызов setCurrentIndex() из QML. - person jpnurmi; 25.04.2017
comment
Оказывается, setCurrentIndex() на самом деле является слотом, поэтому вы уже можете вызывать его из QML, не нарушая привязки. Мы добавим это в документацию, чтобы сделать его официальным. - person jpnurmi; 27.04.2017
comment
Это было то простое решение, которое я искал! Спасибо ;) - person Jon McClung; 27.04.2017

Вы можете искать сигналы. Из документации Qt:

Обработчики сигналов изменения свойств

Сигнал излучается автоматически при изменении значения свойства QML. Этот тип сигнала является сигналом изменения свойства, и обработчики сигналов для этих сигналов записываются в форме on ‹Property› Changed, где ‹Property› - имя свойства, с заглавной первой буквой.

Таким образом, для вашего примера:

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

Таким образом, вы можете просто установить currentIndex для любого из них и быть уверенным, что они останутся «связанными» из-за обработчиков сигналов.

Редактировать:

Как указано jpnurmi, вы также можете использовать Qt.binding так:

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

Это восстановит привязку после назначения статического значения.

person Jon McClung    schedule 24.04.2017