使用Qt时如何打印到控制台


159

我正在使用Qt4和C ++制作计算机图形学中的某些程序。我需要能够在运行时在控制台中打印一些变量,而不是进行调试,但是cout即使添加了这些库,它似乎也不起作用。有没有办法做到这一点?


3
您能否详细说明cout不起作用,因为那肯定可以起作用。你得到一个编译错误。您能否显示不适合您的cout的代码示例?还说明您如何运行该应用程序。您是从控制台还是在IDE中运行它,却看不到输出到其输出窗口?
阿诺德·斯彭斯

只是为了完整性:@ArnoldSpence-没有库,我得到了error: ‘cout’ was not declared in this scope;使用iostream,我得到了error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char>&)(& std::cout)), ...;使用答案中的命令可以正常工作。
sdaau

当问题陈述只是“不起作用”时,很难提供解决方案。请编辑您的问题,以更完整地描述您期望发生的事情以及与实际结果有何不同。请参阅“ 如何询问有关如何做出良好解释的提示”。
Toby Speight

在这种情况下,您应该明确指定那些“变量”是Qt特定的对象(例如QString)。
user202729

Answers:


203

如果足以打印到stderr,则可以使用以下最初用于调试的流:

#include<QDebug>

//qInfo is qt5.5+ only.
qInfo() << "C++ Style Info Message";
qInfo( "C Style Info Message" );

qDebug() << "C++ Style Debug Message";
qDebug( "C Style Debug Message" );

qWarning() << "C++ Style Warning Message";
qWarning( "C Style Warning Message" );

qCritical() << "C++ Style Critical Error Message";
qCritical( "C Style Critical Error Message" );

// qFatal does not have a C++ style method.
qFatal( "C Style Fatal Error Message" );

尽管如注释中所指出,但是请记住,如果QT_NO_DEBUG_OUTPUT已定义qDebug消息,则会将其删除

如果您需要stdout,则可以尝试如下操作(如Kyle Strand所指出的):

QTextStream& qStdOut()
{
    static QTextStream ts( stdout );
    return ts;
}

然后,您可以按以下方式致电:

qStdOut() << "std out!";

1
我问,在不调试的情况下,必须有一个功能允许我在运行时而不是调试期间在控制台中编写消息。
lesolorzanov

11
尽管具有此名称,但该功能与使用调试器进行调试无关。Qt提供了一个方便的功能,用于将输出发送到stderr,可以使用定义将其从编译中删除。因此,它是在运行时实现向控制台输出的一种替代方法。
阿诺德·斯彭斯

非常感谢大家,我正在使用这个:)。我想没有必要再写任何我使用的代码了。谢谢!这非常有用。
lesolorzanov

51
的#include <QDebug>
鸭子

62
请不要对所有控制台输出使用qDebug。仅将其用于真正的调试打印,将qWarning,qCritical和qFatal用于错误和警告。因为使用QT_NO_DEBUG_OUTPUT进行编译时可以删除qDebug语句,以节省性能并阻止应用程序使输出混乱。
JustMaximumPower 2012年

150

我发现最有用:

#include <QTextStream>

QTextStream out(stdout);
foreach(QString x, strings)
    out << x << endl;

14
我不知道为什么不接受答案,但是可以肯定这是最有用的。
Semyon Danilov

4
同意 stderr用于错误(和调试)。这应该是公认的答案,因为它是唯一使用stdout AND qt的答案。
马歇尔·尤班克斯

1
这对我有用
Vincent

2
如果您结合了Goz的答案中有关如何打印错误/警告的信息,以及一些有关实际操作的信息(严重缺乏Goz的答案,但在其下方的注释中提供了信息),那么qDebug()到目前为止,这将是更好的答案(IMO由于OP要求更换某些东西,所以它已经很优越了std::cout,但是40位选民似乎不同意)。
凯尔·斯特兰德

QTextStream qStdout() { return {stdout}; }可能是包装这种包装的一种有用方法,与qWarning()etc 保持一致。也许有些static状态可以避免临时流式传输?
Yakk-Adam Nevraumont

36

写给 stdout

如果您希望将某些内容(例如std::cout)写入应用程序的标准输出中,则只需执行以下操作归功于CapelliC):

QTextStream(stdout) << "string to print" << endl;

如果要避免创建临时QTextStream对象,请遵循以下注释中Yakk的建议,即创建函数以返回以下对象的static句柄stdout

inline QTextStream& qStdout()
{
    static QTextStream r{stdout};
    return r;
}

...

foreach(QString x, strings)
    qStdout() << x << endl;

记得flush流周期性地,以确保实际打印输出。

写给 stderr

注意,上述技术也可以用于其他输出。但是,有许多更易读的书写方式stderr感谢Goz和他的回答下方的评论):

qDebug() << "Debug Message";    // CAN BE REMOVED AT COMPILE TIME!
qWarning() << "Warning Message";
qCritical() << "Critical Error Message";
qFatal("Fatal Error Message");  // WILL KILL THE PROGRAM!

qDebug()如果QT_NO_DEBUG_OUTPUT在编译时打开,则关闭。

(Goz在注释中指出,对于非控制台应用程序,这些应用程序可以打印到与以外的流中stderr。)


注意:所有Qt打印方法都假定const char*参数是带有终止\0字符的ISO-8859-1编码的字符串。


1
QTextStream qStdout() { static QTextStream r{stdout}; return r; }
Yakk-Adam Nevraumont

1
@Yakk好建议!我将结合到我的答案中。
Kyle Strand'3

使用QT5编译时,qFatal()出错。读了一篇帖子,无论如何都不应该去(在那里/工作)...不要使用它!:)
relascope 2015年

1
@KyleStrand您不能为此使用函数吗?template <typename C> constexpr typename std::remove_const<typename std::remove_reference<C>::type>::type& no_const(C* c) { return const_cast<typename std::remove_const<typename std::remove_reference<C>::type>::type&>(*c); } 使用: no_const(this).method()。您可以将该函数作为方法注入到类中,然后甚至不需要通过thisFoo& no_const() const { return ::no_const(this); } 我保证没有错别字。
恢复莫妮卡

1
@Mitch Hm,回顾那些链接和Qt文档,您是对的;我看不到任何迹象表明存在由临时QTextStream对象引起的任何实际已知问题。编辑。
Kyle Strand



8

它还具有类似于prinft的语法,例如:

qDebug ("message %d, says: %s",num,str); 

也非常方便


8

进入项目的Properties -> Linker-> System -> SubSystem,然后将其设置为Console(/S)


1
这(如Kyle Lutz的回答)是特定于构建系统的。
凯尔·斯特兰德

3

包括iostream库又如何呢?coutstd的对象,就像这样:

#include <iostream>

std::cout << "Hello" << std::endl;

1

如果要使用stdio库打印到stderr,则对的调用fflush(stderr)应刷新缓冲区并获得实时日志记录。



0

好了,在研究了Internet上的几个示例之后,这些示例描述了如何将消息从Qt中的GUI输出到stdout,然后,我改进了一个有效的独立示例,该示例涉及通过qDebug()和安装qInstallMessageHandler()将消息重定向到控制台。该控制台将与GUI同时显示,并且在必要时可以隐藏。该代码易于与项目中的现有代码集成。这是完整的示例,只要您遵守License GNU GPL v2,就可以随意使用它。我认为您必须使用某种形式的表格和MainWindow-否则示例将运行,但在强制退出时可能会崩溃。注意:无法通过关闭按钮或菜单关闭退出,因为我已经测试了这些替代方法,并且应用程序最终会不时崩溃。没有关闭按钮,应用程序将稳定,您可以从主窗口将其关闭。请享用!

#include "mainwindow.h"
#include <QApplication>

//GNU GPL V2, 2015-02-07
#include <QMessageBox>
#include <windows.h>
#define CONSOLE_COLUMNS 80
#define CONSOLE_ROWS    5000
#define YOURCONSOLETITLE "Your_Console_Title"

typedef struct{

    CONSOLE_SCREEN_BUFFER_INFOEX conScreenBuffInfoEX;

    HANDLE con_screenbuf;
    HWND hwndConsole;
    HMENU consoleMenu ;
    QString consoleTitle;

    QMessageBox mBox;
    QString localMsg;
    QString errorMessage;
    WINBOOL errorCode;

} consoleT;

static consoleT *console;

BOOL WINAPI catchCTRL( DWORD ctrlMsg ){

        if( ctrlMsg == CTRL_C_EVENT ){

            HWND hwndWin = GetConsoleWindow();
               ShowWindow(hwndWin,SW_FORCEMINIMIZE);
        }

    return TRUE;
}

void removeCloseMenu(){

    int i;

    for( i = 0; i < 10; i++){

        console->hwndConsole = FindWindowW( NULL, console->consoleTitle.toStdWString().data());

        if(console->hwndConsole != NULL)
            break;
    }

    if( !(console->errorCode = 0) && (console->hwndConsole == NULL))
            console->errorMessage += QString("\nFindWindowW error: %1 \n").arg(console->errorCode);

    if( !(console->errorCode = 0) &&  !(console->consoleMenu = GetSystemMenu( console->hwndConsole, FALSE )) )
        console->errorMessage += QString("GetSystemMenu error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = DeleteMenu( console->consoleMenu, SC_CLOSE, MF_BYCOMMAND )))
           console->errorMessage += QString("DeleteMenu error: %1 \n").arg(console->errorCode);
}

void initialiseConsole(){

    console->conScreenBuffInfoEX.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
    console->consoleMenu = NULL;
    console->consoleTitle = YOURCONSOLETITLE;
    console->con_screenbuf = INVALID_HANDLE_VALUE;
    console->errorCode = 0;
    console->errorMessage = "";
    console->hwndConsole = NULL;
    console->localMsg = "";

    if(!(console->errorCode = FreeConsole()))
        console->errorMessage += QString("\nFreeConsole error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = AllocConsole()))
        console->errorMessage += QString("\nAllocConsole error: %1 \n").arg(console->errorCode);

    if( (console->errorCode = -1) && (INVALID_HANDLE_VALUE ==(console->con_screenbuf = CreateConsoleScreenBuffer( GENERIC_WRITE | GENERIC_READ,0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL))))
        console->errorMessage += QString("\nCreateConsoleScreenBuffer error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = SetConsoleActiveScreenBuffer(console->con_screenbuf)))
        console->errorMessage += QString("\nSetConsoleActiveScreenBuffer error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = GetConsoleScreenBufferInfoEx(console->con_screenbuf, &console->conScreenBuffInfoEX)))
        console->errorMessage += QString("\nGetConsoleScreenBufferInfoEx error: %1 \n").arg(console->errorCode);

    console->conScreenBuffInfoEX.dwSize.X = CONSOLE_COLUMNS;
    console->conScreenBuffInfoEX.dwSize.Y = CONSOLE_ROWS;

    if(!(console->errorCode = SetConsoleScreenBufferInfoEx(console->con_screenbuf, &console->conScreenBuffInfoEX)))
       console->errorMessage += QString("\nSetConsoleScreenBufferInfoEx error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = SetConsoleTitleW(console->consoleTitle.toStdWString().data())))
        console->errorMessage += QString("SetConsoleTitle error: %1 \n").arg(console->errorCode);

    SetConsoleCtrlHandler(NULL, FALSE);
    SetConsoleCtrlHandler(catchCTRL, TRUE);

    removeCloseMenu();

    if(console->errorMessage.length() > 0){
        console->mBox.setText(console->errorMessage);
        console->mBox.show();
    }

}

void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg){


    if((console->con_screenbuf != INVALID_HANDLE_VALUE)){

        switch (type) {

        case QtDebugMsg:
            console->localMsg = console->errorMessage + "Debug: " + msg;
            WriteConsoleW(console->con_screenbuf, console->localMsg.toStdWString().data(), console->localMsg.toStdWString().length(), NULL, NULL );
            WriteConsoleA(console->con_screenbuf, "\n--\n", 4, NULL, NULL );
            break;

        case QtWarningMsg:
            console->localMsg = console->errorMessage + "Warning: " + msg;
            WriteConsoleW(console->con_screenbuf, console->localMsg.toStdWString().data(), console->localMsg.toStdWString().length() , NULL, NULL );
            WriteConsoleA(console->con_screenbuf, "\n--\n", 4, NULL, NULL );
            break;

        case QtCriticalMsg:
            console->localMsg = console->errorMessage + "Critical: " + msg;
            WriteConsoleW(console->con_screenbuf, console->localMsg.toStdWString().data(), console->localMsg.toStdWString().length(), NULL, NULL );
            WriteConsoleA(console->con_screenbuf, "\n--\n", 4, NULL, NULL );
            break;

        case QtFatalMsg:
            console->localMsg = console->errorMessage + "Fatal: " + msg;
            WriteConsoleW(console->con_screenbuf, console->localMsg.toStdWString().data(), console->localMsg.toStdWString().length(), NULL, NULL );
            WriteConsoleA(console->con_screenbuf, "\n--\n", 4, NULL, NULL );
            abort();
        }
    }
}



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

    qInstallMessageHandler(messageHandler);

    QApplication a(argc, argv);

    console = new consoleT();
    initialiseConsole();

    qDebug() << "Hello World!";

    MainWindow w;
    w.show();

    return a.exec();
}

0

“构建并运行”>“在终端中运行”的默认设置->启用

使用以下命令刷新缓冲区-> fflush(stdout); 您也可以在printf或中使用“ \ n” cout

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.