【问题标题】:Console output in a Qt GUI app?Qt GUI 应用程序中的控制台输出?
【发布时间】:2011-03-22 14:13:23
【问题描述】:

我有一个在 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();
}

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

【问题讨论】:

  • 你在windows上吗?您确定它没有调出控制台然后立即退出吗?除了基本教程之外,我从未真正使用过 Qt
  • 我在 Windows 上并从命令行运行应用程序。
  • 这实际上是一件很奇怪的事情——我注意到在 GUI 模式下没有输出到控制台,但是如果你从命令行运行程序并将其重定向到文件myprogram.exe &gt; output.txt,那么输出就会落在这个文件。也许像 cat 的 windows 版本这样简单的东西可以轻松解决这个问题?

标签: c++ windows qt qt4


【解决方案1】:

首先你可以尝试刷新缓冲区

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

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

【讨论】:

  • std::endl 顺便说一句没有任何区别。
【解决方案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

【讨论】:

  • fprintf 在我的 GUI 应用程序中不产生任何输出。
  • @neuviemeporte 是的,输出仅适用于控制台应用程序或将显示在 IDE 的调试器输出窗口中
【解决方案3】:

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

其次,qDebug 很花哨:)

第三,您可以尝试将console 添加到您的.proCONFIG,它可能会起作用。

【讨论】:

  • 此应用程序可以在两种模式下运行 - 使用命令行开关的控制台和作为 GUI 的控制台。
  • 就个人而言,控制台是我寻找错误信息的第一个地方:-)
【解决方案4】:

在您的 .pro 中添加

CONFIG          += console

【讨论】:

  • 对不起,与 rubenvb 所说的重复。
【解决方案5】:

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

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

CONFIG += console

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

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

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

【讨论】:

  • 是的,这就是我意识到的——两个应用程序!
  • 有一个小的控制台应用程序来调用主 GUI 应用程序很好,但是有没有办法将输出实时反馈到控制台应用程序,以便用户可以看到发生了什么,或者显示诸如 -h、--version 等的典型输出?
  • 您可以通过调用 FreeConsole 来释放控制台。因此,您的应用程序可能会决定它将在哪种模式下工作,然后在 GUI 模式下运行时隐藏控制台。
  • 请注意,FreeConsole 在 Windows 8 上具有极其危险的行为:stackoverflow.com/questions/12676312/…
【解决方案6】:

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

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

改用QMessageBox 来显示消息。

【讨论】:

  • QMessageBox 可以输出到控制台吗? o.0
【解决方案7】:

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

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

【讨论】:

  • printf、cout 或 qDebug 都不会为我在该配置中的控制台上打印任何内容。
【解决方案8】:

至少对于 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

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

【讨论】:

    【解决方案9】:
    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”!

    【讨论】:

    • 您似乎没有使用 pFileCon。还是我误解了 freopen 的作用?
    • Windows 用户的绝招。你有什么跨平台的推荐吗?
    • 优秀的解决方案。我想补充一点,以获得您需要扩展代码以包含 stderr 的 Qt 控制台行为。我用它来诊断安装在客户端计算机上的“发布”应用程序。在特定的命令行开关上,我的发布应用程序会打开一个控制台。将 stdout 和 stderr 重新路由到它后,控制台会输出我的所有诊断信息和 Qt 的错误,就像在 .pro 文件中使用 CONFIG += console 时一样。
    【解决方案10】:

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

    这种解决方案的好处是:

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

    希望这能让你深思,虽然我还没有资格假设你应该如何做到这一点,但我可以想象我们中的任何人只要稍加搜索/阅读,就可以实现这一目标!

    【讨论】:

      【解决方案11】:

      确保 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...";
      }
      

      【讨论】:

        【解决方案12】:

        我也玩过这个,发现重定向输出有效,但我从未看到控制台窗口的输出,每个 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();
            }
        }
        

        【讨论】:

          【解决方案13】:

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

          CONFIG   += console
          

          真的很有效。除非您明确告诉 QtCreator 在项目上执行 qmake(右键单击项目)并更改源文件中的某些内容,然后重新构建,否则它不会起作用。否则会跳过编译,您仍然不会在命令行上看到输出。 现在我的程序可以在 GUI 和 cmd 行模式下运行。

          【讨论】:

          • 这是很好的反馈。谢谢@柠檬339。现在隐藏使用 GUI 打开的控制台窗口。
          【解决方案14】:

          添加:

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

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

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

          【讨论】:

          • 这不适用于重定向(./executable > out.txt)
          • 我已经花了一些时间研究这个,看起来您可以使用 GetFileType 来确定管道是否处于活动状态。在我修改过的代码中,我设置了 stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));然后,我用条件包装 freopen for stdout: if(stdout_type == FILE_TYPE_UNKNOWN) 这似乎有效地允许进程输出到现有管道(如果可用),但在管道未打开时输出到父控制台。
          • 这是一个简单的修复,在我的 Win7 / Qt 5.10 上使用 QGuiApplication 也需要控制台输出。
          • IMO 这应该是公认的答案,因为它完全符合问题中的要求。它还适用于在 add_executable 中使用 WIN32 的基于 CMake 的 Qt 项目。
          • 别忘了在你的代码中添加#include &lt;Windows.h&gt;
          【解决方案15】:

          简单

          第 1 步: 创建新项目。转到文件->新建文件或项目-->其他项目-->空项目

          第二步:使用下面的代码。

          在 .pro 文件中

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

          第三步: 创建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】:

            这个话题有很多答案。 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 += 控制台”,但是您需要重定向流并自行创建控制台:

            #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,请隐藏控制台并通过退出关闭它。

            【讨论】:

              【解决方案17】:

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

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

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-07-30
                • 2023-03-23
                • 2018-01-12
                • 2014-04-29
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多