从 QML 简单访问 C++ 对象数据

Posted

技术标签:

【中文标题】从 QML 简单访问 C++ 对象数据【英文标题】:Simple acces of C++ object data from QML 【发布时间】:2013-04-17 22:22:17 【问题描述】:

我正在使用 qml 在 Qt/C++ 中制作棋盘游戏。所有重要的游戏数据都在一个类中表示。我的意图是让 qml 表访问这个对象并根据数据绘制游戏板。

将 C++ 数据成员公开给 QML 的最简单方法是什么?

现在我知道这个问题已经被问过了,我已经看到了答案和 Qt 文档。然而,我并不满意。我所看到的,这样做的方法似乎是将 Q_PROPERTY 从我想从 QML 访问的每个变量中取出。这在我看来是乏味和不必要的,更不用说它会将代码拉伸到原始长度的 3 倍,从而使阅读变得更糟。此外,例如,在大多数情况下,我不需要对数据成员写入函数。

当我可以只为我需要的情况编写 Q_INVOKABLE getter 时,为什么还要为 Q_PROPERTY 开销而烦恼?

当我阅读 Qt 项目文档时,我希望它是多么简单的一个示例:“这使得 C++ 数据和函数可以直接从 QML 访问,通常只需很少或无需修改。” em>

class game : public QObject

    Q_OBJECT
public:
    explicit game(QObject *parent = 0);
    colors NPC[3]; // colors being an enum declared elsewhere
    player players[4]; // player is a non-QObject class containing player stats

...
game gMain;
QDeclarativeContext *context = viewer.rootContext();
context->setContextProperty("Game",&gMain);

我理想世界中的 QML:

Image 
    id : Image1
    source:  if (Game.NPC[0] === 0) 
                  if (Game.players[1].LifeCount > 0) 
                      return "pics/FigG.png"
                  
                  else 
                      return "pics/StoneG.png"
                  
             

现在,使用 QML,我实际上可以达到多近的程度,我该怎么做? 我对处理简单的 C++ 样式数组和枚举特别感兴趣(游戏中有很多)——我是否需要编写辅助函数,例如int Game.GetNPCAt(int i) 而不是只使用 Game.NPC[i]

我意识到我不想这样做的方式是久经考验和值得信赖的,并且有充分的理由......但是在我的情况下(小型单人项目)似乎使用大炮杀死苍蝇(虽然 qml 中的 GUI 构建部分非常简单,而且使用起来非常愉快) - 还必须环绕每个数据成员,包括最简单的 int 似乎......太荒谬了。

也许我在某个地方遗漏了什么,在这种情况下,我谦虚地道歉。感谢您对此事的任何想法。

【问题讨论】:

【参考方案1】:

按顺序:

Q_PROPERTY:当您查看page that you quoted 时,他们讨论使用Q_PROPERTY 方法向QML 公开属性。如果你不使用Q_PROPERTY,我的理解是你的变量不会被 QMLViewer 注册(或者你有什么)。 Q_PROPERTY 需要 Q_INVOKABLE 来获取/设置您的变量。但是,如果您不使用Q_PROPERTY,您的类属性将不会出现在 QML 中。

设置图像源:如果您还记得,QML 是 CSS 和 javascript 之间的融合。如果您只是希望根据 Image 元素之外的条件更改图像的源,您可以创建一个 JavaScript 函数来实现您引用的内容:

Image 
    id: Image1

    function getImage()
    
        if (Game.NPC[0] === 0)
        

            if (Game.players[1].LifeCount > 0) 
                      Image1.source="pics/FigG.png";
                  
                  else 
                      Image1.source="pics/StoneG.png";
                  
        
    

但是,该函数不会自行运行:您必须将它与我将在您的 C++ 类中创建的信号相关联(将该函数放在名为 signals: 的标签下(不在 public 内) -- 请参阅here 了解如何编写信号))。根据您的示例,我猜您的 C++ 对象称为Game

Game 
    id: gameKeeper //or whatever you want to name it
    onUpdate: Image1.getImage() //replace onUpdate with your signal


Image 
    id: Image1

    function getImage()
    
        if (gameKeeper.NPC[0] === 0)
        

            if (gameKeeper.players[1].LifeCount > 0) 
                      Image1.source="pics/FigG.png";
                  
                  else 
                      Image1.source="pics/StoneG.png";
                  
        
    

理论上,您应该能够使用 JavaScript 以这种方式引用数组(我自己对 JS 不是很熟悉)。

数组处理:在 C++ 方面,看起来最好的方法是通过 QList。幸运的是,QList 的迭代与普通数组非常相似。我找到了this,这应该会有所帮助——忽略第二个维度。

希望这会有所帮助。

【讨论】:

以上是关于从 QML 简单访问 C++ 对象数据的主要内容,如果未能解决你的问题,请参考以下文章

从 C++ 访问 QML WebView

如何有效地将单个对象的多个 C++ 数据成员公开给 QML?

如何从 C++ 访问 QML ListView 委托项目?

在没有 Q_PROPERTY 定义的情况下从 C++ 访问 QML 对象的属性

如何从 C++ 代码将 QML 对象转换为 QQuickWindow?

QML与Qt C++ 交互机制探讨与总结(转)