从 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?
在没有 Q_PROPERTY 定义的情况下从 C++ 访问 QML 对象的属性