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

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

343624 次浏览

如果足以打印到 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!";

你想打印什么变量? 如果你指的是 QString,那么这些变量需要转换成 c-String。试试:

std::cout << myString.toAscii().data();

将此添加到您的项目文件:

CONFIG += console

我发现 这个最有用:

#include <QTextStream>


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

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

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

也很方便

转到项目的 Properties -> Linker-> System -> SubSystem,然后设置为 Console(/S)

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

在研究了几个互联网上描述如何在 Qt 中将 GUI 中的消息输出到 stdout 的例子之后,我完善了一个可以独立工作的例子,通过 qDebug ()和安装 qInstallMessageHandler ()将消息重定向到控制台。控制台将显示在同一时间作为 GUI,并可以隐藏,如果认为必要的。该代码很容易与项目中的现有代码集成。下面是完整的示例,您可以随意以任何方式使用它,只要您遵守许可 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();
}

写信给 stdout

如果您想要像 std::cout那样将数据写入应用程序的标准输出,您可以简单地执行 以下(归功于 CapelliC) :

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

如果您想避免创建临时 QTextStream对象,请遵循 Yakk 在下面的注释中提出的建议,创建一个函数来返回 stdoutstatic句柄:

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


...


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

请定期将 记录到 flush流中,以确保实际打印输出。

写信给 stderr

注意,上述技术也可以用于其他输出。然而,还有更多可读的方式写到 stderr(都是高兹的功劳和下面的评论他的答案) :

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

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

(Goz 在评论中指出,对于非控制台应用程序,它们可以打印到与 stderr不同的流。)


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

如何包含 Iostream 图书馆并精确地说 Cout性病的一个对象,如下所示:

#include <iostream>


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

「建立及运行」 > 「在终端运行」的预设值-> 启用

使用以下命令刷新缓冲区—— > fflush (stdout) ; 你也可以在 printf或者 cout中使用“ n”。