Cómo imprimir en la consola cuando se usa Qt

159

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, sin depurar, pero coutparece que no funciona incluso si agrego las bibliotecas. ¿Hay alguna forma de hacer esto?

lesolorzanov
fuente
3
¿Puedes explicar si Cout no funciona porque eso debería funcionar? ¿Obtiene un error de compilación? ¿Puedes mostrar un código de ejemplo de cout que no te funcione? También explique cómo está ejecutando la aplicación. ¿Lo está ejecutando desde una consola o desde un IDE y no ve resultados en su ventana de resultados?
Arnold Spence
Solo para completar: @ArnoldSpence: sin bibliotecas, obtengo error: ‘cout’ was not declared in this scope; con iostream, me sale error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char>&)(& std::cout)), ...; usar los comandos en la respuesta en su lugar funciona bien.
sdaau
Es difícil ofrecer soluciones cuando el enunciado del problema es simplemente "no funciona". Por favor, editar su pregunta para dar una descripción más completa de lo que se esperaba a pasar y la diferencia con los resultados reales. Vea Cómo pedir pistas sobre lo que hace una buena explicación.
Toby Speight
En este caso, debe especificar explícitamente que esas "variables" son objetos específicos de Qt (como QString).
user202729

Respuestas:

203

Si es lo suficientemente bueno para imprimir stderr, puede usar las siguientes secuencias originalmente destinadas a la depuración:

#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" );

Aunque como se señaló en los comentarios, tenga en cuenta que los mensajes qDebug se eliminan si QT_NO_DEBUG_OUTPUTse define

Si necesita stdout, puede intentar algo como esto (como ha señalado Kyle Strand):

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

Entonces puede llamar de la siguiente manera:

qStdOut() << "std out!";
Goz
fuente
1
Pregunté, mientras no se depura, debe haber una función que me permita escribir mensajes en la consola durante el tiempo de ejecución, no durante la depuración.
lesolorzanov
11
A pesar de su nombre, esa función no está relacionada con la depuración con un depurador. Es una función conveniente que Qt proporciona para enviar la salida a stderr que se puede eliminar de la compilación con una definición. Por lo tanto, es una alternativa para lograr la salida a la consola en tiempo de ejecución.
Arnold Spence el
Muchas gracias a todos, estoy usando esto :). Supongo que no hay necesidad de que escriba el código que usé. ¡Gracias! Esto ha sido súper útil.
lesolorzanov
51
#include <QDebug>
ducky
62
No use qDebug para toda la salida de la consola. Úselo solo para impresiones de depuración verdaderas, use qWarning, qCritical y qFatal para errores y advertencias. Porque las declaraciones qDebug se pueden eliminar al compilar con QT_NO_DEBUG_OUTPUT para ahorrar rendimiento y evitar que la aplicación desordene la salida.
JustMaximumPower
150

Encontré esto más útil:

#include <QTextStream>

QTextStream out(stdout);
foreach(QString x, strings)
    out << x << endl;
CapelliC
fuente
14
No sé por qué no se acepta la respuesta, pero es la más útil con seguridad.
Semyon Danilov
44
Convenido. stderr es para, bueno, errores (y depuración). Esta debería ser la respuesta aceptada porque es la única que usa stdout AND qt.
Marshall Eubanks
1
Este funcionó para mí, y parecía la forma correcta de generar información a través de Cout
Michael Vincent
2
Si incorpora la información de la respuesta de Goz sobre cómo imprimir errores / advertencias, junto con un poco de información (lamentablemente carente de la respuesta de Goz, pero presente en los comentarios a continuación) sobre lo que qDebug()realmente hace, esta será, con mucho, la respuesta superior (La OMI ya es superior ya que OP está pidiendo algo para reemplazar std::cout, pero los votantes de 40 parecen no estar de acuerdo)
Kyle Strand
QTextStream qStdout() { return {stdout}; }podría ser una forma útil de envolver esto, coherente con qWarning()etc. ¿Y quizás algún staticestado para evitar el daño temporal?
Yakk - Adam Nevraumont
36

Escribiendo a stdout

Si desea algo que, como std::cout, escribe en la salida estándar de su aplicación, simplemente puede hacer lo siguiente ( crédito a CapelliC ):

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

Si desea evitar crear un QTextStreamobjeto temporal , siga la sugerencia de Yakk en los comentarios a continuación de crear una función para devolver un staticidentificador para stdout:

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

...

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

Recuerde realizar flushla transmisión 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 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()está cerrado si QT_NO_DEBUG_OUTPUTestá activado 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 a stderr).


NOTA: Todos los métodos de impresión Qt suponen que los const char*argumentos son cadenas codificadas ISO-8859-1 con \0caracteres de terminación .

Kyle Strand
fuente
1
QTextStream qStdout() { static QTextStream r{stdout}; return r; }?
Yakk - Adam Nevraumont
1
@Yakk ¡Buena sugerencia! Incorporaré a mi respuesta.
Kyle Strand
qFatal () obtiene un error al compilar con QT5. una lectura de una publicación, que de todos modos no era (estar allí / trabajar) ... ¡no la uses! :)
relascopio
1
@KyleStrand ¿No puedes usar una función para eso? 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); } Uso: no_const(this).method() . Podrías inyectar esa función como método en la clase, y luego ni siquiera necesitarías aprobar this: Foo& no_const() const { return ::no_const(this); } No hay errores tipográficos, lo prometo.
Vuelva a instalar Mónica
1
@ Mitch Hm, revisando esos enlaces y la documentación de Qt, tienes razón; No veo nada que indique que hay algún problema real conocido causado por QTextStreamobjetos temporales . Editado
Kyle Strand
32

Agregue esto a su archivo de proyecto:

CONFIG += console
Kyle Lutz
fuente
55
No se proporcionó información en la pregunta sobre qué sistema de compilación se está utilizando. Esto solo es relevante cuando se usa qmake.
Kyle Strand
19

¿Qué variables quieres imprimir? Si te refieres a QStrings, esos deben convertirse a c-Strings. Tratar:

std::cout << myString.toAscii().data();
Sebastian Negraszus
fuente
8
@CoderaPurpa Necesitas agregar#include <iostream>
Sebastian Negraszus
myString.toUtf8().data()es mejor porque imprime caracteres fuera del rango ASCII. Caracteres chinos, por ejemplo
peterchaula
8

También tiene una sintaxis similar a prinft, por ejemplo:

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

Muy práctico también

ulitosCoder
fuente
8

Vaya al Proyecto Properties -> Linker-> System -> SubSystem, luego configúrelo Console(/S).

Hijo vu
fuente
1
Esto (como la respuesta de Kyle Lutz) es específico del sistema de construcción.
Kyle Strand
3

¿Qué hay de incluir la biblioteca iostream y precisar que cout es un objeto de std como este:

#include <iostream>

std::cout << "Hello" << std::endl;
Cottet Esmeralda
fuente
1

Si está imprimiendo en stderr usando la biblioteca stdio, una llamada a fflush(stderr)debería vaciar el búfer y obtener un registro en tiempo real.

Andrew Prock
fuente
1
#include <QTextStream>
...
qDebug()<<"Bla bla bla";
Amir Touitou
fuente
0

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 para redirigir mensajes a una consola, a través de qDebug () e instalar 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éntase libre de usarla de la forma que desee, siempre y cuando se adhiera a la Licencia GNU GPL v2. Tiene que usar una forma de algún tipo y una ventana principal, creo; de lo contrario, la muestra se ejecutará, pero probablemente se bloqueará cuando se vea obligado a salir. Nota: no hay forma de salir mediante un botón de cierre o un menú de cierre 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();
}
usuario2178077
fuente
0

"build & run"> Predeterminado para "Ejecutar en terminal" -> Habilitar

para vaciar el búfer use este comando -> fflush (stdout); también puedes usar "\ n" en printfo cout.

r.shams
fuente