c++ - Cómo imprimir en la consola cuando se usa Qt
cout (12)
Estoy usando Qt4 y C ++ para hacer algunos programas en gráficos de computadora. Necesito poder imprimir algunas variables en mi consola en tiempo de ejecución, no de depuración, pero cout
no parece funcionar incluso si agrego las bibliotecas. ¿Hay alguna forma de hacer esto?
Escribiendo a stdout
Si desea algo que, como std::cout
, escriba en la salida estándar de su aplicación, simplemente puede hacer this ( crédito a CapelliC ):
QTextStream(stdout) << "string to print" << endl;
Si desea evitar la creación de un objeto QTextStream
temporal, siga la sugerencia de Yakk en los comentarios siguientes sobre cómo crear una función para devolver un identificador static
para stdout
:
inline QTextStream& qStdout()
{
static QTextStream r{stdout};
return r;
}
...
foreach(QString x, strings)
qStdout() << x << endl;
Recuerde flush
la secuencia periódicamente para asegurarse de que la salida se imprima realmente.
Escribiendo a stderr
Tenga en cuenta que la técnica anterior también se puede utilizar para otras salidas. Sin embargo, hay formas más legibles de escribir en stderr
( crédito a Goz y los comentarios debajo de su respuesta):
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()
se cierra si QT_NO_DEBUG_OUTPUT
se activa en tiempo de compilación.
(Goz señala en un comentario que para las aplicaciones que no son de consola, estas pueden imprimirse en una secuencia diferente de stderr
).
NOTA: Todos los métodos de impresión Qt suponen que los argumentos const char*
son cadenas codificadas ISO-8859-1 con caracteres /0
finalizadores.
¿Qué pasa si incluimos la biblioteca iostream y precisamos que cout es un objeto de la siguiente manera:
#include <iostream>
std::cout << "Hello" << std::endl;
¿Qué variables quieres imprimir? Si se refiere a QStrings, esos deben convertirse a c-Strings. Tratar:
std::cout << myString.toAscii().data();
Agregue esto a su archivo de proyecto:
CONFIG += console
Bueno, después de estudiar varios ejemplos en Internet que describen cómo enviar mensajes desde una GUI en Qt a stdout, he refinado un ejemplo independiente de trabajo al redirigir mensajes a una consola, a través de qDebug () e instalando qInstallMessageHandler (). La consola se mostrará al mismo tiempo que la GUI y se puede ocultar si se considera necesario. El código es fácil de integrar con el código existente en su proyecto. Aquí está la muestra completa y siéntete libre de usarla de la manera que quieras, siempre y cuando te adhieras a la licencia GNU GPL v2. Tienes que usar un formulario de algún tipo y una ventana principal, creo, de lo contrario la muestra se ejecutará, pero probablemente se bloquee cuando se vea obligado a abandonarla. Nota: no hay forma de salir mediante un botón de cerrar o cerrar un menú porque he probado esas alternativas y la aplicación se bloqueará eventualmente de vez en cuando. Sin el botón de cerrar, la aplicación será estable y puede cerrarla desde la ventana principal. ¡Disfrutar!
#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();
}
Encontré this más útil:
#include <QTextStream>
QTextStream out(stdout);
foreach(QString x, strings)
out << x << endl;
Probé todas las muestras de arriba:
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" );
Todas las pantallas excepto las qDebug()
; No se puede encontrar dónde se puede invocar QT_NO_DEBUG
. qDebug()
funcionó bien para mí, pero desapareció con ubuntu 17.10
Gracias
Si es lo suficientemente bueno para imprimir en stderr
, puede usar las siguientes transmisiones originalmente diseñadas para la depuración:
//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" );
Aunque como se señala en los comentarios, tenga en cuenta que los mensajes QDebug se eliminan si se define QT_NO_DEBUG_OUTPUT
Si necesita stdout, podría intentar algo como esto (como ha señalado Kyle Strand):
QTextStream& qStdOut()
{
static QTextStream ts( stdout );
return ts;
}
A continuación, puede llamar de la siguiente manera:
qStdOut() << "std out!";
Si está imprimiendo en stderr utilizando la biblioteca stdio, una llamada a fflush(stderr)
debe limpiar el búfer y obtener el registro en tiempo real.
También tiene una sintaxis similar a prinft, por ejemplo:
qDebug ("message %d, says: %s",num,str);
Muy útil también
Vaya a Properties -> Linker-> System -> SubSystem
del proyecto Properties -> Linker-> System -> SubSystem
, luego Properties -> Linker-> System -> SubSystem
en Console(/S)
.
#include <QTextStream>
...
qDebug()<<"Bla bla bla";