将基于Qt GUI的应用程序转换为控制台或批处理应用程序

时间:2013-12-13 14:29:01

标签: qt user-interface console batch-processing

我有一个基于Qt GUI的完整应用程序,但现在我需要在批处理模式(控制台)的某种管道中使用此应用程序。我尝试了几种方法,但没有一种能按预期工作。这就是我现在所拥有的:

QApplication a(argc, argv);
MyMainWindow *w = new MyMainWindow();
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
a.exec();

这就是我需要的:

QApplication a(argc, argv);

QString project_path = argv[1];

MyMainWindow *w = new MyMainWindow();
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));

w->loadPrjFile(project_path);
w->analyze();
w->exportResults();

a.exec();

所以,基本上我需要的是允许应用程序通过命令行(而不是文件对话框)获取 project_path 并执行用户通常使用GUI遵循的方法。问题是这些方法应该阻止,因为人们应该等待前一个方法完成。

应用程序本身应该阻止,在shell中执行时,应该等待整个执行完成后再退出。因为它应该作为控制台应用程序工作,所以界面也应该被隐藏。

如果您知道如何做到这一点,我真的很感谢如何做到这一点的代码示例。

3 个答案:

答案 0 :(得分:4)

你遇到的问题是你正在尝试开发一个控制台应用程序,但仍然使用Gui小部件,例如QMainWindow。您需要首先将Gui类与主项目中的所有其他类分开。

我建议你创建一个派生自QObject的类,它处理你需要的东西; loadPrjFile,analyze和exportResults。

然后在MainWindow中使用此新类的实例作为GUI项目,并将其直接用于控制台项目。

class Worker : public QObject
{
    Q_OBJECT

    public:
        void loadPrjFile(const QString& path);
        void analyze();
        void exportResults();
};


class MyMainWindow : QMainWindow
{
    private:
        Worker m_pWorkerObject;
};

如果您正在开发不需要Gui的控制台项目,则可以使用QCoreApplication而不是QApplication。

请注意,调用app.exec()会启动Qt处理消息,因此,只有在需要消息循环来处理事件时才需要它,这可能不是控制台应用程序的情况,具体取决于您的应用程序的功能。

答案 1 :(得分:1)

要在具有GUI的应用程序中从命令行读取参数,您可以在代码中的任何位置使用全局指针qApp。例如,如果您希望能够将GUI应用程序与文件类型相关联,则此功能特别有用,因为操作系统会将文件名提供给您的应用程序(至少在Windows中可用)。

您可以在this thread中看到我对同一问题给出的详细答案,以及相应文档的链接,由于某些原因,这些文档不在最新版本的Qt中。

第二部分并不那么容易。

您可以在调用a.exec()之前使用w-> setVisible(false);隐藏您的主窗口,但据我所知,您将修改每个具有对话框的方法,以便在检测到时对命令行参数作出反应,并禁用对话,或者如果没有相关内容则使用正常对话框检测到参数。

如果你只需要调用主窗口中没有与用户交互的方法,那么它就不会那么多了,你可能会因为没有调用a.exe而逃脱(当且仅当没有部分时)你的代码是在批处理模式下使用信号和插槽),这实际上是启动GUI的主循环,在这种情况下不需要。

这样的事可能有用:

QApplication a(argc, argv);
MyMainWindow *w = new MyMainWindow();


if(1 < qApp->arguments().count()) //Command line arguments detected
{
  QString project_path = qApp->arguments().at(1);

  w->loadPrjFile(project_path);
  w->analyze();
  w->exportResults();


}
else    //No command line arguments detected
{
  a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
  a.exec();
}

另一方面,如果函数loadPrjFile(),analyze();和exportResults()是插槽,而不是,如你的代码所示,主窗口的方法,它们不会被顺序调用,你将别无选择,只能使用信号和插槽,所以每个功能可以通知下一个它完成了它的工作,因此必须调用a.exec

答案 2 :(得分:1)

这个答案显示了我在一段时间后提出的解决方案。我会把它放在这里因为它对其他人有用。代码如下所示:

QApplication a(argc, argv);

QString project_file = argv[1];

MyMainWindow *w = new MyMainWindow();
w->setVisible(false);
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
w->setBatchMode(true);

QObject::connect(w,SIGNAL(loadingFinished()),w,SLOT(analyze()));
QObject::connect(w,SIGNAL(analysisFinished()),w,SLOT(exportResults()));
QObject::connect(w,SIGNAL(exportingFinished()),w,SLOT(close()));

w->loadPrjFile(project_file);

a.exec();

主要考虑因素是:

  • w-&gt; setVisible(false)用于隐藏MainWindow,正如@Dissident penguin所指出的那样。

  • w-&gt; setBatchMode(true)用于设置一个类变量,该变量用于压制整个代码中的所有其他对话框,如@Dissident penguin所指出的那样。在函数内部,我只使用if语句包含对话框代码,如:

    if(!_batchMode){// show dialog}

  • 满足顺序执行的要求并不容易。我必须创建两个信号: loadingFinished() analyzeFinished() exportedFinished()。然后我分别在 loadPrjFile() analyze() exportResults()函数的末尾发出它们。这样我就保证他们按顺序执行并且等待另一个人。这是必需的,因为插槽在Qt。

  • 中异步执行
  • 最后,我无法取出 a.exec()方法,因为如果我这样做,程序就无法正常运行。我想这是因为我还在使用GUI,它只是隐藏了。这样,仍然需要 a.exec()