Qt GUI应用程序中的控制台输出?

时间:2010-07-29 08:14:17

标签: c++ windows qt qt4

我在Windows上运行了一个Qt GUI应用程序,它允许传递命令行选项,在某些情况下我想向控制台输出一条消息,然后退出,例如:

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  if (someCommandLineParam)
  {
    std::cout << "Hello, world!";
    return 0;
  }

  MainWindow w;
  w.show();

  return a.exec();
}

但是,当我从命令提示符运行应用程序时,不会显示控制台消息。有谁知道我怎么能让它发挥作用?

17 个答案:

答案 0 :(得分:44)

Windows并不真正支持双模式应用程序。

要查看控制台输出,您需要创建一个控制台应用程序

CONFIG += console

但是,如果双击该程序以启动GUI模式版本,则会出现一个控制台窗口,这可能不是您想要的。为了防止出现控制台窗口,您必须创建一个GUI模式应用程序,在这种情况下,您不会在控制台中输出。

一个想法可能是创建第二个小应用程序,它是一个控制台应用程序并提供输出。这可以调用第二个来完成工作。

或者您可以将所有功能放在DLL中然后创建两个版本的.exe文件,它们具有调用DLL的非常简单的主要功能。一个用于GUI,一个用于控制台。

答案 1 :(得分:11)

添加:

#ifdef _WIN32
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
    freopen("CONOUT$", "w", stdout);
    freopen("CONOUT$", "w", stderr);
}
#endif

位于main()的顶部。这将仅在程序在控制台中启动时才能输出到控制台,并且在其他情况下不会弹出控制台窗口。如果要在控制台外运行应用程序时创建控制台窗口以显示消息,可以将条件更改为:

if (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole())

答案 2 :(得分:5)

void Console()
{
    AllocConsole();
    FILE *pFileCon = NULL;
    pFileCon = freopen("CONOUT$", "w", stdout);

    COORD coordInfo;
    coordInfo.X = 130;
    coordInfo.Y = 9000;

    SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coordInfo);
    SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE),ENABLE_QUICK_EDIT_MODE| ENABLE_EXTENDED_FLAGS);
}

int main(int argc, char *argv[])
{
    Console();
    std::cout<<"start@@";
    qDebug()<<"start!";

你不能像其他人所说的那样使用std :: cout,即使某些代码不能包含“qdebug”,我的方式也很完美!

答案 3 :(得分:5)

使用QT += gui时无法向控制台输出消息。

fprintf(stderr, ...)也无法打印输出。

使用QMessageBox来显示消息。

答案 4 :(得分:4)

哦,您可以在使用QT += guiCONFIG += console时输出消息。

您需要printf("foo bar"),但cout << "foo bar"不起作用

答案 5 :(得分:2)

我在下面使用这个标题来表示我的项目。希望它有所帮助。

#ifndef __DEBUG__H
#define __DEBUG__H

#include <QtGui>    

static void myMessageOutput(bool debug, QtMsgType type, const QString & msg) {

    if (!debug) return;

    QDateTime dateTime = QDateTime::currentDateTime();
    QString dateString = dateTime.toString("yyyy.MM.dd hh:mm:ss:zzz");

    switch (type) {

        case QtDebugMsg:
            fprintf(stderr, "Debug: %s\n", msg.toAscii().data());
            break;
        case QtWarningMsg:
            fprintf(stderr, "Warning: %s\n", msg.toAscii().data());
            break;
        case QtCriticalMsg:
            fprintf(stderr, "Critical: %s\n", msg.toAscii().data());
            break;
        case QtFatalMsg:
            fprintf(stderr, "Fatal: %s\n", msg.toAscii().data());
            abort();
    }
}

#endif

PS:如果您将来想要,可以将dateString添加到输出中。

答案 6 :(得分:2)

你可能想要调查的东西,至少对于windows来说,是windows api中的AllocConsole()函数。它调用GetStdHandle几次来重定向stdout,stderr等等。(一个快速测试显示这并不完全按我们的意愿去做。你确实得到了一个与你的其他Qt一起打开的控制台窗口,但你不能输出到它。据推测,因为控制台窗口是打开的,有一些方法可以访问它,获取它的句柄,或以某种方式访问​​和操作它。这是MSDN文档,对于那些有兴趣解决这个问题的人来说:

AllocConsole(): http://msdn.microsoft.com/en-us/library/windows/desktop/ms681944%28v=vs.85%29.aspx

GetStdHandle(...): http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx

(我将此添加为评论,但规则阻止我这样做......)

答案 7 :(得分:0)

在你的.pro中添加

CONFIG          += console

答案 8 :(得分:0)

首先,为什么需要在发布模式构建中输出到控制台?当有gui时,没有人会想到那里看看......

其次,qDebug很花哨:)

第三,您可以尝试将console添加到.pro的{​​{1}},这可能有效。

答案 9 :(得分:0)

这可能是对其他答案的疏忽,或者可能是用户确实需要控制台输出的要求,但对我来说显而易见的答案是创建一个可以显示或隐藏的辅助窗口(带有一个复选框)或按钮)通过将文本行附加到文本框小部件并将其用作控制台来显示所有消息?

这种解决方案的好处是:

  • 一个简单的解决方案(提供所有显示的是一个简单的日志)。
  • 将“控制台”小部件停靠在主应用程序窗口上的功能。 (无论如何,在Qt。)。
  • 创建多个控制台的能力(如果超过1个线程等)。
  • 从本地控制台输出到通过网络发送日志到客户端的非常简单的更改。

希望这给你提供了思考的食物,虽然我没有任何资格可以假设你应该如何做到这一点,我可以想象这是我们任何一个人都可以通过一点点搜索/阅读来实现的!< / p>

答案 10 :(得分:0)

确保Qt5Core.dll与您的应用程序可执行文件位于同一目录中。

我在Qt5中遇到了一个与控制台应用程序类似的问题: 如果我从Qt Creator启动应用程序,输出文本是可见的, 如果我打开cmd.exe并在那里启动相同的应用程序,则无法看到输出。 很奇怪!

我通过将 Qt5Core.dll 复制到包含应用程序可执行文件的目录来解决它。

这是我的小型控制台应用程序:

#include <QCoreApplication>
#include <QDebug>

int main(int argc, char *argv[])
{
    int x=343;
    QString str("Hello World");
    qDebug()<< str << x<<"lalalaa";

    QTextStream out(stdout);
    out << "aldfjals alsdfajs...";
}

答案 11 :(得分:0)

我也玩过这个,发现重定向输出有效,但我从未看到输出到控制台窗口,这是每个Windows应用程序都有的。到目前为止,这是我的解决方案,直到找到ShowWindow和GetConsoleWindow的Qt替代品。

从没有参数的命令提示符运行它 - 获取窗口。从带有参数的命令提示符运行(例如cmd aaa bbb ccc) - 您可以在命令提示符窗口中获得文本输出 - 就像您对任何Windows控制台应用程序所期望的那样。

请原谅这个蹩脚的例子 - 它代表了大约30分钟的修补。

#include "mainwindow.h"
#include <QTextStream>
#include <QCoreApplication>
#include <QApplication>
#include <QWidget>
#include <windows.h>

QT_USE_NAMESPACE

int main(int argc, char *argv[])
{
    if (argc > 1)   {
        // User has specified command-line arguments
        QCoreApplication a(argc, argv);
        QTextStream  out(stdout);
        int     i;

        ShowWindow (GetConsoleWindow(),SW_NORMAL);
        for (i=1; i<argc; i++)
             out << i << ':' << argv [i] << endl;
        out << endl << "Hello, World" << endl;
        out << "Application Directory Path:" << a.applicationDirPath() << endl;
        out << "Application File Path:" << a.applicationFilePath() << endl;
        MessageBox (0,(LPCWSTR)"Continue?",(LPCWSTR)"Silly Question",MB_YESNO);
        return 0;
    } else  {
        QApplication a(argc, argv);
        MainWindow w;

        w.setWindowTitle("Simple example");
        w.show();
        return a.exec();
    }
}

答案 12 :(得分:0)

这个话题有很多答案。 0.0

所以我尝试使用 Qt5.x从Win7到Win10 。我花了几个小时才能找到一个好的工作解决方案,它不会在链中的任何地方产生任何问题:

#include "mainwindow.h"

#include <QApplication>

#include <windows.h>
#include <stdio.h>
#include <iostream>

//
// Add to project file:
// CONFIG += console
//

int main( int argc, char *argv[] )
{
    if( argc < 2 )
    {
    #if defined( Q_OS_WIN )
        ::ShowWindow( ::GetConsoleWindow(), SW_HIDE ); //hide console window
    #endif
        QApplication a( argc, argv );
        MainWindow *w = new MainWindow;
        w->show();
        int e = a.exec();
        delete w; //needed to execute deconstructor
        exit( e ); //needed to exit the hidden console
        return e;
    }
    else
    {
        QCoreApplication a( argc, argv );
        std::string g;
        std::cout << "Enter name: ";
        std::cin >> g;
        std::cout << "Name is: " << g << std::endl;
        exit( 0 );
        return a.exec();
    }
}

我也尝试了没有“CONFIG + = console”,但是你需要重定向流并自己创建控制台:

#ifdef _WIN32
if (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole()){
    freopen("CONOUT$", "w", stdout);
    freopen("CONOUT$", "w", stderr);
    freopen("CONIN$", "r", stdin);
}
#endif

这只有在您通过调试器启动时才有效,否则所有输入也会指向系统。意味着,如果您通过std :: cin键入名称,系统会尝试将该名称作为命令执行。 (很奇怪)

此尝试的另外两个警告是,您不能使用:: FreeConsole()它不会关闭它,如果您通过控制台启动它,应用程序将不会关闭

此主题最后有一个Qt help section in QApplication。我在那里用一个应用程序尝试了这个例子,它不适用于GUI ,它在无限循环中停留在某个地方并且GUI不会被渲染或者只是崩溃:

QCoreApplication* createApplication(int &argc, char *argv[])
{
    for (int i = 1; i < argc; ++i)
        if (!qstrcmp(argv[i], "-no-gui"))
            return new QCoreApplication(argc, argv);
    return new QApplication(argc, argv);
}

int main(int argc, char* argv[])
{
    QScopedPointer<QCoreApplication> app(createApplication(argc, argv));

    if (qobject_cast<QApplication *>(app.data())) {
       // start GUI version...
    } else {
       // start non-GUI version...
    }

    return app->exec();
}

因此,如果您正在使用Windows和Qt,只需使用控制台选项,如果需要GUI则隐藏控制台并通过退出将其关闭。

答案 13 :(得分:0)

一种解决方案是运行powershell并将输出重定向到所需的任何流。

以下是从cmd.exe运行powershell并将my_exec.exe输出重定向到控制台和output.txt文件的示例:

powershell ".\my_exec.exe | tee output.txt"

答案 14 :(得分:-1)

在经历了相当长时间的完全相同问题的斗争后,我发现只是

CONFIG   += console

真的有诀窍。在您明确告诉QtCreator在项目上执行qmake(右键单击项目)并更改源文件中的内容然后重建之前,它不会工作。否则将跳过编译,您仍然无法在命令行上看到输出。 现在我的程序在GUI和cmd行模式下工作。

答案 15 :(得分:-1)

轻松

第1步:创建新项目。 Go File-&gt; New File or Project - &gt;其他项目 - &gt;空项目

第2步:使用以下代码。

在.pro文件中

QT +=widgets
CONFIG += console
TARGET = minimal
SOURCES += \ main.cpp

第3步: 创建main.cpp并复制以下代码。

#include <QApplication>
#include <QtCore>

using namespace  std;

QTextStream in(stdin);
QTextStream out(stdout);

int main(int argc, char *argv[]){
QApplication app(argc,argv);
qDebug() << "Please enter some text over here: " << endl;
out.flush();
QString input;
input = in.readLine();
out << "The input is " << input  << endl;
return app.exec();
}

我在代码中创建了必要的对象以供您理解。

刚刚运行

如果您希望程序在某些条件下获得多个输入。然后通过Main.cpp中的以下代码

#include <QApplication>
#include <QtCore>

using namespace  std;

QTextStream in(stdin);
QTextStream out(stdout);

int main(int argc, char *argv[]){
    QApplication app(argc,argv);
    qDebug() << "Please enter some text over here: " << endl;
    out.flush();
    QString input;
    do{
        input = in.readLine();
        if(input.size()==6){
            out << "The input is " << input  << endl;   
        }
        else
        {
            qDebug("Not the exact input man");
        }
    }while(!input.size()==0);

    qDebug(" WE ARE AT THE END");

    // endif
    return app.exec();
} // end main

希望它教育你。

美好的一天,

答案 16 :(得分:-3)

首先,您可以尝试刷新缓冲区

std::cout << "Hello, world!"<<std::endl;

对于更多基于Qt的日志记录,您可以尝试使用qDebug。