【问题标题】:How to use QStatemachine to influence a ListView?如何使用 QStatemachine 来影响 ListView?
【发布时间】:2016-12-17 15:35:15
【问题描述】:

我有这个 Projekt,它使用 QStatemachine 来管理 UI,我想在其中添加自定义列表。 UI 应该只由关键事件操作。据我了解,我需要 qml 端的 ListView 。

ListView 的委托只对鼠标输入或直接键输入作出反应。但是我使用 C++ 中的 QStatemachine 来操作它,因为它正在处理 UI 的所有关键事件。 当我按下右箭头键时,我想要发生的事情是将列表向左移动。
(currentItem 总是在屏幕中间。)

所以我的 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++ 状态机是一个向 qml 发送信号的 QStatemachine。

如何将信号绑定到 Listview 的委托?

【问题讨论】:

  • 您可以直接从 QML 使用StateMachine。它比使用 C++ 类更容易、更快捷。
  • 嗯,我已经用 c++ 完成了状态机,它相当大。所以如果不从头开始,我就无法改变它。
  • 然后只需将其连接到 QML。它已经是一个 QObject 派生的,因此您可以将其公开为上下文属性并使用它的信号和插槽。

标签: c++ qt listview qml qstatemachine


【解决方案1】:

最简单的方法是让状态机设置“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 端以一种很好的声明性方式使用状态数据,就像它自己处理状态一样

【讨论】:

    【解决方案2】:

    第一步 - 将状态机公开为上下文属性,使其对 qml 可见:

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

    第二步 - 使用Connections 元素建立连接:

    Connections {
      target: SM
      onSomeSignal: doSomeStuff()
    }
    

    【讨论】:

    • 如果我使用 QTQuickView 而不是引擎,是否可以公开状态机?
    • 是的,QQuickView 也有 rootContext()
    • 好的。那我怎样才能使用 onSignal 来操作 listView 呢?我不能只覆盖delegate:。我可以吗?
    • @user1997675 - 我不是通灵者,我不知道你的 C++ 代码是做什么的以及它是如何做到的。您问如何将状态机信号绑定到 qml 对象,我提供了答案。
    • 我不是故意冒犯你的。我只是想了解这是如何工作的。我对 QT 很陌生,我不明白如何将它与 ListView 一起使用。还是谢谢。
    猜你喜欢
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 2013-09-30
    • 2016-10-05
    相关资源
    最近更新 更多