我有一个基于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中执行时,应该等待整个执行完成后再退出。因为它应该作为控制台应用程序工作,所以界面也应该被隐藏。
如果您知道如何做到这一点,我真的很感谢如何做到这一点的代码示例。
答案 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()。