首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >多个QApplication实例

多个QApplication实例
EN

Stack Overflow用户
提问于 2017-09-19 15:14:54
回答 1查看 5.7K关注 0票数 7

我想知道在同一个过程中有多个QApplication/QCoreApplication实例意味着什么(问题),以及如何解决有关它的一些问题。

场景如下:我想在开源第三方应用程序上做一个包装器,以便将其作为可选插件转换为可嵌入的小部件(应用程序基本上包含在单个QMainWindow-based接口上)。

这样的项目在很大程度上依赖于QCoreApplication派生类,但基本上是因为它被用作一个已经存在的单例。我能够修改代码(为了将QMainWindow公开为一个可嵌入的小部件,我必须这样做),尽管由于该项目的复杂性,我不能简单地删除父类。

因此,最终的应用程序将有自己的QApplication (在开始时创建),然后选择加载前面提到的插件(从而创建第二个QCoreApplication)。只有第一个(主) QApplication用于事件循环(QCoreApplication::exec())。

我知道的事实是,QCoreApplication是一个单身。在我的测试中,单例总是指向最后创建的实例:

代码语言:javascript
运行
复制
qDebug() << qApp;
auto app1 = new QApplication(argc, argv);
qDebug() << qApp;
auto app2 = new TheOtherQApplication(argc, argv);
qDebug() << qApp;

输出是

QObject(0x0) QApplication(0x6f9400,name = "test") 在QCoreApplication中断言失败:“应该只有一个应用程序对象”,文件kernel\qcoreapplication.cpp,第595行 TheOtherQApplication(0x2550dc0,name = "test") TheOtherQApplication(0x2550dc0,name = "test") TheOtherQApplication(0x2550dc0,name = "test")

可以看到,在创建第二个QApplication之后,它将替换全局实例。有什么办法解决这个问题吗?由于插件是可选的,显而易见的答案(将主QApplication放在第二位)不是一个合适的选项。

此外,是否还有多个QApplication实例的其他含义?或者都与事件循环(已检查)和单例相关?

注意:这是一个基于QT4.7的项目,因为第三方依赖关系还没有完全更新。它计划在一年左右的时间内迁移到最新版本,但目前我必须处理4.7。

顺便说一下,我已经复习了几个相关的问题,包括this one,但这并没有提供任何有用的信息。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-09 15:37:06

据我所理解,使用两个或多个Q*Applications (QCoreApplicationQGuiApplicationQApplication)意味着:

  1. 当创建第二个应用程序(或更多)时,断言在调试模式下失败。在释放模式下没有崩溃。
  2. Q*Application的每个实例化都会更新单个实例(也就是说,qApp总是指向最后一个实例)。
  3. 全局属性(如应用程序名称和版本)将随实例一起传输并覆盖以前的属性。
  4. 任何连接到Q*Application插槽的信号都会调用单例的时隙,即使在创建最新实例之前已经连接。
  5. 只有连接到最新Q*Application信号的插槽才会被调用(它们不会传输到新实例)。
  6. 当创建新的Q*Application实例时,不会传输翻译器。
  7. 如果最后一个Q*Application被销毁,那么该单例将变为null (它不会返回到前一个实例)。

您可以使用以下代码并切换USE_TWO_QAPPS来测试这些特性

代码语言:javascript
运行
复制
#include <QtCore>

#define USE_TWO_QAPPS

int main(int argc, char* argv[])
{
  QTranslator tr1;

  QCoreApplication a1(argc, argv);
  a1.setApplicationName("a1");
  a1.installTranslator(&tr1);
  qDebug() << qApp << &a1;
  qDebug() << "a1.applicationName() =" << a1.applicationName();

  // qApp == &a1
  QObject::connect(&a1, &QCoreApplication::aboutToQuit, []() {
    // point 5, never called with  Q*Application
    qDebug() << "Hello world from a1!";
  });
  QTimer::singleShot(2000, &a1, &QCoreApplication::quit); // as if connected to latest qApp, point 4

#ifdef USE_TWO_QAPPS
// if (true) { // uncomment to test point 7
  QCoreApplication a2(argc, argv);
  a2.setApplicationName("a2");
  qDebug() << qApp << &a1 << &a2; // test point 2
  qDebug() << "a2.applicationName() =" << a2.applicationName();
  qDebug() << "a1.applicationName() =" << a1.applicationName(); // as if called from qApp, point 3
  QObject::connect(&a2, &QCoreApplication::aboutToQuit, []() {
    qDebug() << "Hello world from a2!";
  });
// } // uncomment to test point 7
#endif

  qDebug() << qApp->removeTranslator(&tr1); // false if the translator is not installed, point 6
  a1.installTranslator(&tr1); // it is installed in the latest instance (as if called from qApp)
  qDebug() << qApp->removeTranslator(&tr1);

  return qApp->exec();
}

一个Q*Application结果

QCoreApplication(0xfafb74) QCoreApplication(0xfafb 74) a1.applicationName() = "a1“ 真的 真的 来自a1的世界你好!

使用两个Q*Application的结果

QCoreApplication(0xbefb2c) QCoreApplication(0xbefb2c) a1.applicationName() = "a1“ 断言失败:“应该只有一个应用程序对象”,文件########\qtbase\src\corelib\kernel\qcoreapplication.cpp,行769 QCoreApplication(0xbefb1c) QCoreApplication(0xbefb2c) QCoreApplication(0xbefb1c) a2.applicationName() = "a2“ a1.applicationName() = "a2“ 错误 真的 来自a2的世界你好!

当测试点7时,a2在退出if语句时被销毁。在这种情况下,对Q*Application方法的每一次调用都会引发警告,并且不会执行(它们不会崩溃,也不会中断断言)。即使在从上一个应用程序调用:a1.installTranslator(&tr1);时,也会发生这种情况。

QApplication::installTranslator:请先实例化QApplication对象

注意:使用2010进行测试。Qt版本为4.7和5.6.1-1,两者的结果相同

更新:--此答案的更清晰的代码版本可在https://github.com/cbuchart/stackoverflow/blob/master/46304070-multiple-qapplication-instances/main.cpp中获得

在注释之后,这段代码还测试了当所有QApplication对象被销毁,然后再次创建时会发生什么。结果:如预期,无特殊情况发生,似乎没有副作用。

结论

考虑到这些要点,使用两个或两个以上的Q*Application似乎是可能的,更关键的是,在除最后一个Q*Application之外的任何一个Q*Application上,都会丢失到信号的连接,并且没有安装翻译器。另外,如果最后一个实例被销毁,那么就没有可用的应用程序,因此您应该处理这些情况(例如,如果卸载创建最后一个实例的DLL )。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46304070

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档