C++ 应用程序中的 QML,反之亦然

2022-01-19 00:00:00 qt qml c++

考虑一个简单的 GUI 显示相当复杂的计算输出的情况.

Consider the case of a simple GUI displaying the output of rather elaborate calculation.

现在我想使用 QML 编写一个漂亮的自定义 GUI.
我还想用 QT C++ 编写我的后台应用程序.

Now I would like to write a nice, custom GUI using QML.
I would also like to write my background app in QT C++.

我坐在 QT 文档前想知道如果我
1) 应该编写一个 QML 应用程序 并以某种方式将我的 C++ 类嵌入其中(这是绝对可能的)或者如果我
2) 应该写一个 C++ 应用程序并以某种方式将 QML GUI 嵌入其中并从我的类中修改 QML 属性(这又是可能的)

I'm sitting in front of the QT documentation and wonder if I
1) should write a QML application and somehow embed my C++ classes in it (which is absolutely possible) or if I
2) should write a C++ application and somehow embed the QML GUI in it and modify QML properties from my classes (which is again possible)

我已经在 C++ 中使用 QT Widgets 为 GUI 编写了所有内容.我只想将 GUI 移动到 QML 并保留 C++ 类,即使我愿意重写 GUI 的接口.

I already wrote everything in C++ using QT Widgets for the GUI. I only want to move the GUI to QML and keep the C++ classes even though I am willing to rewrite the interface to the GUI.

可能的分析器:

以下标记的解决方案建议保留 C++ 类并专门通过 SIGNALS 和 SLOTS 接口 GUI.所以基本上我最终得到了一个 main.cpp,它实例化了我的主要工作类并像这样显示 QML GUI:

The marked solution below suggested keeping the C++ classes and interface the GUI exclusively through SIGNALS and SLOTS. So basically I ended up with a main.cpp that instantiates my main working class and displays the QML GUI like this:

QQuickView viewer;
viewer.setSource(QUrl("./qml/main.qml"));
viewer.show();

然后我添加了 myClass 并给了我一个对象来进行连接:

then I added myClass and got me an object to do the connections:

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 以接收要显示的数据.

When implementing the slots and signals in the C++ classes you must use QVariant objects to transfer the data. The QML file then implements SIGNALS e.g. for clicked buttons and SLOTS to receive data to display.

这正是我所希望的.对我的非 GUI 代码的唯一更改是通过 SIGNALS 和 SLOTS 进行所有交互.现在我什至可以在我的应用程序中使用这两种 GUI(QML/Widgets).

This is exactly what I was hoping for. The only change to my non GUI code was to do all the interactions via SIGNALS and SLOTS. Now I can even use both GUIs (QML / Widgets) for my application.

推荐答案

只需用 C++ 编写您的核心逻辑,将其与信号和插槽接口,您就可以将相同的组件与小部件和 QML 一起使用.

Just write your core logic in C++, interface it with signals and slots, and you can use the same component with widgets and also with QML.

这不是火箭科学,C++ 逻辑允许与 C++ 和 QML、JS 逻辑一起使用 - 只有 QML.C++ 和 Qt API 是更合理的解决方案,因为从 JS 中您实际上无法访问 Qt API 的那么多功能,只有少数方法被移植"到 QML 世界中.但是所有的高性能数据容器和执行性能本身都是 C++ 的.

It is not rocket science, C++ logic allows usage with C++ and QML, JS logic - only QML. C++ and the Qt API is the more sound solution, because from JS you don't really have access to that much functionality of the Qt APIs, only a few methods are "ported" into the QML world. But all the high performance data containers and the execution performance itself is in C++.

如果你只需要显示结果而控制台还不够好,我宁愿继续使用 QtWidgets,因为添加声明性模块会显着减慢编译速度.小部件模块现在是独立的,因此即使使用 QtWidgets(在 Qt4 中它是 QtGui 的一部分),您也可以添加额外"模块,但它更轻.使用小部件对核心逻辑进行原型设计后,您可以实现 QML 接口并将其连接到现有的信号/插槽/属性和使用它们的绑定.

If you only need to display results and console is not good enough, I'd rather keep to QtWidgets, because adding the declarative module slows compilation down significantly. The widget module is standalone now, so you are adding "extra" module even with QtWidgets (in Qt4 it was part of QtGui) but it is lighter. After you use widgets for prototyping your core logic, you can then implement a QML interface and just hook that up to the existing signals/slots/properties and bindings using them.

不,您不会在 C++ 类中嵌入 QML,相反,C++ 是更底层的层,用于创建 QML 组件.至于实际的实例化,您可以采用两种方式 - 如果您将基于 QObject 的类注册到 QML 引擎,则可以在 QML 中实例化它.或者您可以在 C++ 中实例化该类,并仅使其在 QML 上下文中可用――这并不重要.如果您需要单个对象,最好在 C++ 中的 main() 函数中实例化它,并使其在 QML 上下文中可用,如果它是您打算大量实例化的组件 - 然后创建一个 QML零件.

And no, you don't embed QML in C++ classes, it is the other way around, C++ is the more low-level layer, which is used to create QML components. As for the actual instantiation, you can go both ways - if you register a QObject based class to the QML engine, you can instantiate it in QML. Or you could instantiate the class in C++ and only make it available in the QML context - it doesn't really matter. If you need a single object, you better instantiate it in C++ in the main() function and make it available in the QML context, if it is components you intend to instantiate a lot - then create a QML component.

您可以在 QML 中使用 JS 对核心逻辑进行原型设计,然后如果您愿意,也可以将其移植到 C++.这看起来是双倍的努力,但如果你把床铺好,它实际上会提高生产力,因为在 QML 中原型设计要快得多,捕捉错误更安全和信息丰富,如果你的 API 做得好,移植 JS 代码对 C++ 来说通常是一个小麻烦――用具体类型替换一些 var,用 -> 替换一些 . 等等.

You could prototype the core logic with JS in QML and later port it to C++ if you want too. It looks like twice the effort, but if you make your bed right it is actually a productivity increase, because prototyping is that much faster in QML, catching errors is much safer and informative, and if you make your API well, porting the JS code to C++ is usually a minor nuisance - replace some vars with concrete types, replace some . with -> and stuff like that.

您真正希望最终在 C++ 中进行的任何精细计算".每次计算完成时,您可以简单地将其作为信号发出,并自动将结果显示到信号连接的任何插槽中,无论是在小部件中还是在 QML 中,甚至同时在两者中.

Any "elaborate calculation" you really WANT to ultimately do in C++. Every time the calculation is completed, you can simply emit it as a signal, and automatically display the result to whatever slot the signal is connected, be that in a widget or in QML, or even both at the same time.

相关文章