考虑一个简单的 GUI 显示相当复杂的计算输出的情况。
现在我想使用 QML 编写一个漂亮的自定义 GUI。
我还想用 QT C++ 编写我的后台应用程序。
我坐在 QT 文档前,想知道
如果我
1) 应该编写一个 QML 应用程序 并以某种方式将我的 C++ 类嵌入其中
(这是绝对可能的)或者如果我
2) 应该编写一个C++ 应用程序
并以某种方式在其中嵌入 QML GUI 并从我的类中修改 QML 属性
(这又是可能的)
我已经使用 QT Widgets 为 GUI 用 C++ 编写了所有内容。我只想将 GUI 移至 QML 并保留 C++ 类,即使我愿意重写 GUI 的界面。
可能的答案:
下面标记的解决方案建议保留 C++ 类并通过 SIGNALS 和 SLOTS 专门连接 GUI。所以基本上我最终得到了一个 main.cpp,它实例化了我的主要工作类并像这样显示 QML GUI:
QQuickView viewer;
viewer.setSource(QUrl("./qml/main.qml"));
viewer.show();
然后我添加了 myClass 并得到了一个对象来进行连接:
MyClass myClass;
QQuickItem* item = viewer.rootObject();
QObject::connect(item, SIGNAL(buttonClicked()), &myClass, SLOT(mySlot()));
QObject::connect(&myClass, SIGNAL(mySignal(QVariant)), item, SLOT(updateGUI(QVariant)));
在 C++ 类中实现槽和信号时,您必须使用 QVariant 对象来传输数据。然后 QML 文件实现 SIGNALS,例如用于单击按钮和 SLOTS 以接收要显示的数据。
这正是我所希望的。对我的非 GUI 代码的唯一更改是通过 SIGNALS 和 SLOTS 进行所有交互。现在我什至可以在我的应用程序中同时使用这两种 GUI(QML/Widgets)。
只需用 C++ 编写您的核心逻辑,将其与信号和槽接口(interface),您就可以将同一组件与小部件以及 QML 一起使用。
这不是火箭科学,C++ 逻辑允许与 C++ 和 QML、JS 逻辑一起使用 - 仅 QML。 C++ 和 Qt API 是更合理的解决方案,因为从 JS 您实际上无法访问 Qt API 的那么多功能,只有少数方法被“移植”到 QML 世界中。但所有高性能数据容器和执行性能本身都在 C++ 中。
如果您只需要显示结果而控制台不够好,我宁愿继续使用 QtWidgets,因为添加声明性模块会显着降低编译速度。小部件模块现在是独立的,因此即使使用 QtWidgets(在 Qt4 中它是 QtGui 的一部分),您也要添加“额外”模块,但它更轻。在使用小部件对核心逻辑进行原型(prototype)设计后,您可以实现 QML 接口(interface)并将其连接到现有信号/槽/属性和使用它们的绑定(bind)。
而且不,您不会将 QML 嵌入到 C++ 类中,恰恰相反,C++ 是更底层的层,用于创建 QML 组件。至于实际实例化,您可以采用两种方式 - 如果您将基于 QObject
的类注册到 QML 引擎,您可以在 QML 中实例化它。或者您可以在 C++ 中实例化该类,并仅使其在 QML 上下文中可用——这并不重要。如果您需要单个对象,您最好在 main()
函数中用 C++ 实例化它,并使其在 QML 上下文中可用,如果它是您打算实例化很多的组件 - 然后创建一个 QML零件。
您可以在 QML 中使用 JS 对核心逻辑进行原型(prototype)设计,如果您愿意,也可以稍后将其移植到 C++。这看起来是两倍的努力,但如果你把床整理好,实际上会提高生产率,因为在 QML 中制作原型(prototype)要快得多,捕获错误更安全、信息量更大,如果你把 API 做好,移植 JS 代码到 C++ 通常是一个小麻烦——将一些 var
替换为具体类型,将一些 .
替换为 ->
等等。
您真正想最终在 C++ 中完成的任何“详细计算”。每次计算完成时,您都可以简单地将其作为信号发出,并自动将结果显示到信号连接的任何插槽中,无论是在小部件中还是在 QML 中,甚至同时显示在两者中。