繁体   English   中英

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

[英]Console output in a Qt GUI app?

我有一个在 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 并不真正支持双模式应用程序。

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

CONFIG += console

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

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

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

添加:

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

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

if (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole())
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”,我的方法也是完美的!

这个话题的答案太多了。 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() 它不会关闭它,如果您通过控制台启动它,应用程序将不会关闭。



最后在 QApplication 中有一个Qt 帮助部分关于这个主题。 我在那里用一个应用程序尝试了这个例子,但它对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,则隐藏控制台并通过退出关闭它。

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

fprintf(stderr, ...)也不能打印输出。

改用QMessageBox来显示消息。

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

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

您可能想要研究的东西,至少对于 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

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

我在下面的项目中使用了这个标题。 希望能帮助到你。

#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添加到输出中。

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

这种解决方案的好处是:

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

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

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

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

其次,qDebug 很花哨:)

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

在您的 .pro 添加

CONFIG          += console

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

在与完全相同的问题进行了相当长时间的斗争后,我发现这很简单

CONFIG   += console

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

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

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

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

简单

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

Step2:使用下面的代码。

在 .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

希望对你有所启发。

再会,

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM