Скрыть первый или последний элемент в представлении пути

#qt #qml #carousel #qt6

Вопрос:

Я написал простую карусель на QML. Я запускаю Qt 6.2.0 под Ubuntu 20.04.

 import QtQuick

PathView {
    id: view

    property int item_width: 864
    property int item_gap: 250

    anchors.fill: parent
    anchors.bottomMargin: 150
    anchors.topMargin: 50
    pathItemCount: 3
    preferredHighlightBegin: 0.5
    preferredHighlightEnd: 0.5
    highlightRangeMode: PathView.StrictlyEnforceRange
    highlightMoveDuration: 1000
    snapMode: PathView.SnapToItem
    rotation: -90

    model: modelContent
    delegate: DelegateContent { }

    path: Path {
        startX: -item_gap; startY: view.height / 2
        PathAttribute { name: "iconScale"; value: 0.7 }
        PathAttribute { name: "iconOpacity"; value: 0.1 }
        PathAttribute { name: "iconOrder"; value: 0 }
        PathLine {x: view.width / 2; y: view.height / 2; }
        PathAttribute { name: "iconScale"; value: 1 }
        PathAttribute { name: "iconOpacity"; value: 1 }
        PathAttribute { name: "iconOrder"; value: 9 }
        PathLine {x: view.width   item_gap; y: view.height / 2; }
    }

    Component.onCompleted: {
        gesture.gestureFired.connect(gestureFired)
    }

    onCurrentIndexChanged: {
        itemAtIndex(0).visible = currentIndex < (count - 1)
    }

    function gestureFired(type) {
        switch (type) {
        case 1:
            if (view.currentIndex > 0) view.decrementCurrentIndex();
            break;

        case 2:
            if (view.currentIndex < view.count - 1) view.incrementCurrentIndex();
            break;
        }
    }
}
 

Это работает очень хорошо. Изменение текущего индекса выполняется только программно ( gestureFired сигнал с C ). Как вы можете видеть, кругового поведения не существует.

Следовательно, я хочу скрыть первый элемент (когда выбран последний) или последний элемент (когда выбран первый).

Я попробовал использовать приведенный выше код:

 onCurrentIndexChanged: {
    itemAtIndex(0).visible = currentIndex < (count - 1)
}
 

Идея заключается в следующем: если currentIndex это последний элемент ( = count - 1 ) visible , свойство первого элемента должно быть ложным.

Но это не работает:

Ошибка типа: Значение равно нулю и не может быть преобразовано в объект

О какой «Ценности» идет речь? Я отладил currentIndex и count , и они оба действительны (4 и 5).

Какой правильный способ добиться такого поведения?

Комментарии:

1. Я не согласен на изменение тега с qt5 на qt6 . qt5 имеет 1,6 тыс. наблюдателей, qt6 всего 31! И различия не так уж велики…

2. Qt6 вносит большие изменения, поэтому это не Qt 5.16, а Qt 6. Так что лучше использовать этот тег. Если вы хотите обратиться к наблюдателям, посмотрите на соответствующий тег Qt, который имеет 21,7 тыс. Другие теги обычно указывают среду. С другой стороны, если вы проверите активность сообщества Qt в SO, вы увидите, что нас немного (вероятно, меньше 50).

Ответ №1:

Простое решение состоит в том, чтобы выполнить привязку в делегате:

 import QtQuick

Column {
    id: root

    required property int index

    // mapping model roles
    required property string name

    visible: _internals.calculateVisibility()

    QtObject {
        id: _internals

        function calculateVisibility() {
            console.log(index, root.PathView.isCurrentItem, root.PathView.view.currentIndex)
            if ((root.index === (root.PathView.view.count - 1)) amp;amp; (root.PathView.view.currentIndex === 0))
                return false;
            else if ((root.index === 0) amp;amp; (root.PathView.view.currentIndex === (root.PathView.view.count - 1)))
                return false;
            return true;
        }

    }

    Text {
        id: nameText

        text: root.name
        font.pointSize: 16
        color: root.PathView.isCurrentItem ? "red" : "blue"
    }

}
 

Комментарии:

1. Из любопытства, какова цель встраивания a function в a QtObject ? Я могу заявить об этом даже без этого, и, похоже, это тоже работает.

2. Ваше решение почти сработало! Единственное предостережение заключается в том, что при изменении текущего индекса (перемещении элемента) ранее скрытый делегат теперь виден! И это неприятно видеть.

3. @Mark Идея состоит в том, чтобы скрыть функции, которые не должны быть общедоступными. Это та же самая причина, потому что в C есть публичное, защищенное и частное.

4. В качестве уродливого обходного пути я добавил Timer , что задерживает переключение root.visibility с false true одного и того же количества view.highlightMoveDuration