Как использовать QStatemachine для влияния на ListView?

У меня есть этот Projekt, который использует QStatemachine для управления пользовательским интерфейсом, где я хочу добавить настраиваемый список. Предполагается, что пользовательским интерфейсом манипулируют только ключевые события. Насколько я понимаю, мне нужен ListView на стороне qml.

Делегат ListView реагирует только на ввод с помощью мыши или прямой ввод с клавиатуры. Но я использовал QStatemachine в C++ для управления им, поскольку он обрабатывает все ключевые события для пользовательского интерфейса. Когда я нажимаю клавишу со стрелкой вправо, я хочу, чтобы список был смещен влево.
(CurrentItem всегда в середине экрана.)

это начальное состояние lisfview

введите описание изображения здесь

Так что мой ListView выглядит так в данный момент.

Component {
            id:myDelegation
            Item {
               x: 50
               width: 80
               height: 60
               Rectangle {
                  width: 60
                  height: 60

                  Text {
                    text: name
                    anchors.centerIn: parent
                  }

                  color: parent.ListView.isCurrentItem ? "red" : "steelblue";
                  scale: parent.ListView.isCurrentItem ? 1.5 : 1;
              }

          }
        }


        ListView {
            id: listView1
            x: 0
            y: 50
            width: 1920
            height: 214
            orientation: ListView.Horizontal
            spacing: 4
            model: TileList{}
            delegate: myDelegation
            preferredHighlightBegin: width / 2 - 10
            preferredHighlightEnd: width / 2 + 10
            highlightRangeMode: ListView.StrictlyEnforceRange
        }

C++ Statemachine - это QStatemachine, который отправляет сигналы в qml.

Как мне связать сигналы с делегатом Listview?

2 ответа

Решение

Шаг первый - представить конечный автомат как свойство контекста, чтобы он был виден qml:

engine.rootContext()->setContextProperty("SM", stateMachinePtr);

Шаг второй - использовать Connections Элемент для установления соединения:

Connections {
  target: SM
  onSomeSignal: doSomeStuff()
}

Самый простой способ - просто установить конечный автомат на "currentIndex".

Обычным шаблоном является наличие объекта интерфейса, который соединяет QML и QStateMachine.

class StateInterface : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int currentIndex MEMBER m_currentIndex NOTIFY currentIndexChanged)

public:
    explicit StateInterface(QObject *parent = 0);

signals:
    void currentIndexChanged() const;

private:
    int m_currentIndex;
};

Экземпляр этого объекта предоставляется QML через механизм "свойства контекста"

StateInterface stateInterface;
qmlEngine->rootContext()->setContextProperty("_stateInterface", &stateInterface);

И используется в QML по мере необходимости

ListView {
    currentIndex: _stateInterface.currentIndex
}

QStateMachine использует то же самое stateInterface объект в качестве объекта назначения государственной собственности

QState *beginState = new QState(stateMachine);
beginState->assignProperty(&stateInterface, "currentIndex", 0);
// and so on.

Объект StateInterface также может предоставлять слоты, которые будут использоваться QML для изменения состояния. Например

public slots:
    void triggerReset() { emit trigger reset(); }

signals:
    void reset();

И QStateMachine может, например, затем реагировать на эти сигналы с переходом сигнала в beginState

Подводя итог этой технике:

  1. QStateMachine контролирует состояние приложения
  2. все данные о состоянии, представляющие интерес для QML, предоставляются через один или несколько объектов интерфейса
  3. сторона QML использует данные о состоянии хорошим, декларативным способом, как если бы она сама выполняла обработку состояния
Другие вопросы по тегам