【问题标题】:Qt create object in c++ and expose to QMLQt 在 C++ 中创建对象并暴露给 QML
【发布时间】:2017-01-16 20:18:51
【问题描述】:

我正在尝试开发一款游戏,但不仅与游戏相关,还与任何事物相关。 我的问题是:您如何在 c++ 上创建/删除/管理对象并在 qml 中出现/消失/更改?

我知道很多用户会告诉我阅读

http://doc.qt.io/qt-4.8/qtbinding.html

http://doc.qt.io/qt-5/qtqml-cppintegration-contextproperties.html

http://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html

http://doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html

等等……

我已经阅读了所有这些。我知道如何以某种方式使用它,例如更改数字的示例,这是一个属性并且它暴露给 QML,因此它会自动更改,但这不是我的问题。

让我们以一些简单的代码为例

class Unit {

int posX, posY;
int energy;

void move()...
void create()...
void kill()
}

然后我们将在主子类和所有必要的子类中实现 C++ 中的所有逻辑。

Game.cpp 
class Game {
QList<Unit> listUnits;

moveUnits() {
for (int i = 0; i < units.size(); i++){
Unit unit;
unit.move();
}

createNewUnit(){
Unit unit = new Unit();
listUnits.append(unit);
}
}

On the other side will have Unit.qml 

Item{
property int posX;
property int posY;
Animation on X {...}
....    
}

这基本上是处理与Unit相关的UI,但我再说一遍,所有的逻辑都将在c++中再次完成。

在前面提到的例子中,我希望,当我创建一个新单元时,它会直接出现在 QML 中。

怎么办?我真的很确定可以做到,而且我确定很简单,我只是没有发现。我不需要代码,只需要提示、参考或教程。

如果解决方案真的在我之前写的一封电子邮件中,我请你更详细地解释它,因为我仍然没有发现。

非常感谢!

【问题讨论】:

    标签: c++ qt qml


    【解决方案1】:

    这是将 C++ 连接到 QML 的方法

    • 让你的 C++ 类继承自 QObject(这意味着它还应该在 public: 上方有 Q_OBJECT
    • 在您的一些公共方法前面添加 Q_INVOKABLE 宏,以便可以从 QML 调用它们。例如Q_INVOKABLE int doStuff(int myParam);

    • 在您的主文件中,注册该类以便 QML 可以找到它:qmlRegisterType&lt;Foo&gt;("MyFoo", 1, 0, "Foo");

    • 在 QML 文件 import MyFoo 1.0 中导入 C++ 类(注意它是 1.0,因为在 qmlRegisterType 中,我传递了参数 1 和 0)
    • 您现在可以将 C++ 类添加到 QML 文件中。 Foo { id: foo} 并且可以从 QML 的其他地方调用您的方法,例如

      函数 qmlDoSomething(val){ var newInt = foo.doStuff(val) }

    如果你想动态创建 QML 组件,你可以这样做:

    function addComponent(){
      var comp = Qt.createComponent("ComponentFile.qml")
      var sprite = comp.createObject(myParent) //myParent should be whatever you want to add the component to
    }
    

    如果您希望 QML 响应 C++ 消息,请向 C++ 添加信号

    signals:
          void makeComponent(QString message);
    

    然后在 QML Widget 中,您可以放置​​一个函数用于何时调用此信号

    Foo{
    id: foo
    onMakeComponent: { 
       console.log(message); 
       addComponent()
     }
    }
    

    如果您不熟悉信号的工作原理,这很简单。在 C++ 方法中,您只需使用关键字 emit 然后将其称为方法

    void myFunc(){
       //Do some stuff
       emit(makeComponent(someString));
    }
    

    如果您希望新创建的 QML 元素将数据发送回 C++

    • 给你的组件一个标识符
    • 将组件信号连接到 C++ 类
    • 当您的组件发出信号时,使其在对 C++ 的调用中包含其标识符
    function addComponent(componentName){
       var comp = Qt.createComponent("ComponentFile.qml")
       var sprite = comp.createObject(myParent)
       sprite.name = componentName
       sprite.mySignal.connect(foo.modifyComponent)
    }
    
    //In ComponentFile.qml
    signal mySignal(string val)
    
    function sendSignal(){
       mySignal(name)
    }
    

    总之,我已经解释了如何:

    • 让 C++ 在 QML 中调用函数
    • 如何从 QML 调用 C++ 函数
    • 如何在 QML 中动态创建新元素
    • 如何让这些新元素调用 C++ 函数

    这应该是您在 QML 和 C++ 之间传递数据所需的一切

    【讨论】:

    • 这就是重点。这一切我已经知道了。我的问题是,例如,当我创建一个新元素时,我需要发送一个信号直到 qml 来创建与该对象关联的关联 qml 对象。我
    • 抱歉,我不太明白你在问什么。 addComponent() 方法不符合您的要求吗?
    • 对不起,我解释得不够好。我试图实现这个架构,我在 C++ 中创建对象,这个对象的视觉表示是 QML。 addComponent() 方法是从 QML 创建对象,与从 c++ 创建对象不同。此外,一旦创建了该对象,如何将该对象引用到 C++。最后,我的目标是在 C++ 中使用逻辑,在 QML 中使用 UI/Visual。也许我没有正确使用 QML 架构或其他东西。再次感谢您的帮助
    • 您不能直接从 C++ 创建 QML 元素。动态创建一个新的 QML 元素并将其信号连接到 C++ 插槽。如果 C++ 想要与新元素交互,让 C++ 发出一个信号(就像它对 makeComponent 所做的那样),除了让它传递你想要修改的元素的名称作为参数。我最近的编辑解释了如何做到这一点
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 2010-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多