代码之家  ›  专栏  ›  技术社区  ›  Patrick Avery

我可以使用QCommandLineParser来确定GUI模式还是CLI模式?

  •  1
  • Patrick Avery  · 技术社区  · 7 年前

    实例化的QApplication的类型取决于使用哪种模式:QApplication应用于GUI模式,QCoreApplication应用于CLI模式,因为Qt的GUI部分不应实例化为CLI模式(因为CLI模式不使用或不需要它们)。

    我可以通过类似以下的代码来实现:

    std::unique_ptr<QCoreApplication> app = 
        (cliMode) ? std::make_unique<QCoreApplication>(argc, argv)
                  : std::make_unique<QApplication>(argc, argv);
    
    // Do some other stuff...
    
    return app->exec();
    

    因为我已经在使用Qt了,所以使用QCommandLineParser来解析我的参数是有意义的。在解析参数之后,我想对它们进行分析,以确定我们应该在GUI模式还是CLI模式下运行。然而,这样做越来越困难。

    我注意到的第一个问题是Linux上的以下问题(这在较早版本的Qt5中没有发生,但在较新版本中确实发生):

    $ ./myQtApplication --help
    QCoreApplication::arguments: Please instantiate the QApplication object first
    Segmentation fault (core dumped)
    

    --help 命令而没有实例化QApplication对象。我通过手动解析参数来查看是否 --救命 这是一个论点。如果是,请继续并实例化QCoreApplication,解析参数,然后退出。

    .app 在终端中输入文件或类型 $ open myQtApplication.app ,我会得到一个神秘的错误:

    LSOpenURLsWithRole() failed with error -10810 for the file ./myQtApplication.app
    

    由于这是一个相当隐晦的错误,我花了很长时间才弄清楚这个错误是由QCommandLineParser在实例化QApplication对象之前被使用引起的。

    1. 手动分析 main() 函数来确定 --cli 通过了。
    2. 运行QCommandLineParser来处理其余的参数。

    这不是一个非常干净的方法,因为我现在有两个参数解析器:一个用来确定 已通过,其余的用于其他参数。

    我想主要的问题是:我可以使用QCommandLineParser来确定是实例化QCoreApplication对象还是QApplication对象?

    1 回复  |  直到 7 年前
        1
  •  4
  •   Kuba hasn't forgotten Monica    7 年前

    当然,您可以使用解析器-只要 QCoreApplication 已经存在。如果 --cli 选项不存在,您将切换到 QApplication . 回想一下,您可以完全控制应用程序对象的生存期。

    这适用于Windows和OS X上的Qt 4.8和5.11:

    // https://github.com/KubaO/stackoverflown/tree/master/questions/app-cli-gui-switch-52649458
    #include <QtGui>
    #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
    #include <QtWidgets>
    #endif
    
    struct Options {
       bool cli;
    };
    
    static Options parseOptionsQt4() {
       Options opts = {};
       for (auto arg : QCoreApplication::arguments().mid(1)) {
          if (arg == "--cli")
             opts.cli = true;
          else
             qFatal("Unknown option %s", arg.toLocal8Bit().constData());
       }
       return opts;
    }
    
    static Options parseOptions() {
       if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) return parseOptionsQt4();
    #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
       Options opts = {};
       QCommandLineParser parser;
       QCommandLineOption cliOption("cli", "Start in command line mode.");
       parser.addOption(cliOption);
       parser.process(*qApp);
       opts.cli = parser.isSet(cliOption);
       return opts;
    #endif
    }
    
    int main(int argc, char *argv[]) {
       QScopedPointer<QCoreApplication> app(new QCoreApplication(argc, argv));
       auto options = parseOptions();
       if (options.cli) {
          qDebug() << "cli";
       } else {
          qDebug() << "gui";
          app.reset();
          app.reset(new QApplication(argc, argv));
       }
    
       if (qobject_cast<QApplication *>(qApp))
          QMessageBox::information(nullptr, "Hello", "Hello, World!");
       QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
       return app->exec();
    }