我正在使用 Qt4 和 C++ 制作一些计算机图形程序。我需要能够在运行时在控制台中打印一些变量,而不是调试,但cout
即使我添加库似乎也不起作用。有没有办法做到这一点?
11 回答
如果它足以打印到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 消息,则会删除
如果你需要标准输出,你可以尝试这样的事情(正如 Kyle Strand 指出的那样):
QTextStream& qStdOut()
{
static QTextStream ts( stdout );
return ts;
}
然后,您可以按如下方式调用:
qStdOut() << "std out!";
我发现这个最有用:
#include <QTextStream>
QTextStream out(stdout);
foreach(QString x, strings)
out << x << endl;
写给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 编码字符串。
将此添加到您的项目文件中:
CONFIG += console
你想打印什么变量?如果您的意思是 QStrings,则需要将它们转换为 c-Strings。尝试:
std::cout << myString.toAscii().data();
它还具有类似于 printft 的语法,例如:
qDebug ("message %d, says: %s",num,str);
也很方便
转到项目的Properties -> Linker-> System -> SubSystem
,然后将其设置为Console(/S)
。
包括iostream 库和精确的cout是这样的std对象怎么样:
#include <iostream>
std::cout << "Hello" << std::endl;
如果您使用 stdio 库打印到 stderr,则调用fflush(stderr)
应该刷新缓冲区并让您获得实时日志记录。
好吧,在研究了 Internet 上描述如何将消息从 Qt 中的 GUI 输出到标准输出的几个示例之后,我改进了一个独立的工作示例,通过 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();
}
“构建和运行”>“在终端中运行”的默认值 -> 启用
要刷新缓冲区,请使用此命令 --> fflush(stdout); 您也可以在printf
或中使用“\n” cout
。