Come stampare su console quando si utilizza Qt


159

Sto usando Qt4 e C ++ per creare alcuni programmi in computer grafica. Devo essere in grado di stampare alcune variabili nella mia console in fase di esecuzione, non di debug, ma coutnon sembra funzionare anche se aggiungo le librerie. C'è un modo per fare questo?


3
Puoi spiegarci che cout non funziona perché dovrebbe sicuramente funzionare. Ricevi un errore di compilazione. Puoi mostrare un esempio di codice di cout che non funziona per te? Spiega anche come stai eseguendo l'applicazione. Lo stai eseguendo da una console o da un IDE e non vedi l'output nella sua finestra di output?
Arnold Spence,

Solo per completezza: @ArnoldSpence - senza librerie, ottengo error: ‘cout’ was not declared in this scope; con iostream, ottengo error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char>&)(& std::cout)), ...; usando i comandi nella risposta invece funziona benissimo.
sdaau,

È difficile offrire soluzioni quando l'affermazione del problema è semplicemente "non funziona". Si prega di modificare la tua domanda per dare una descrizione più completa di ciò che si aspetta di accadere e come questo si differenzia dai risultati effettivi. Vedi Come chiedere suggerimenti su ciò che rende una buona spiegazione.
Toby Speight,

In questo caso, è necessario specificare esplicitamente che quelle "variabili" sono oggetti specifici di Qt (come QString).
user202729

Risposte:


203

Se è abbastanza buono per la stampa stderr, è possibile utilizzare i seguenti stream originariamente destinati al debug:

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

Sebbene, come sottolineato nei commenti, tieni presente che i messaggi qDebug vengono rimossi se QT_NO_DEBUG_OUTPUTdefiniti

Se hai bisogno di stdout potresti provare qualcosa del genere (come ha sottolineato Kyle Strand):

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

È quindi possibile chiamare come segue:

qStdOut() << "std out!";

1
Ho chiesto, pur non eseguendo il debug, deve esserci una funzione che mi consenta di scrivere messaggi in console durante il runtime, non durante il debug.
lesolorzanov,

11
Nonostante il nome, tale funzione non è correlata al debug con un debugger. È una comoda funzione che Qt fornisce per inviare l'output a stderr che può essere rimosso dalla compilation con un define. Quindi è un'alternativa per ottenere l'output sulla console in fase di esecuzione.
Arnold Spence,

Grazie mille, lo sto usando :). Immagino che non sia necessario che io scriva il codice che ho usato. Grazie! Questo è stato super utile.
lesolorzanov,

51
#include <QDebug>
ducky

62
Non utilizzare qDebug per tutto l'output della console. Usalo solo per stampe di debug reali, usa qWarning, qCritical e qFatal per errori e avvisi. Perché le istruzioni qDebug possono essere rimosse durante la compilazione con QT_NO_DEBUG_OUTPUT per salvare le prestazioni e impedire all'applicazione di ingombrare l'output.
JustMaximumPower

150

Ho trovato questo molto utile:

#include <QTextStream>

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

14
Non so perché la risposta non sia accettata, ma è sicuramente la più utile.
Semyon Danilov,

4
Concordato. stderr è per errori (e debug). Questa dovrebbe essere la risposta accettata perché è l'unica che usa stdout AND qt.
Marshall Eubanks,

1
Questo ha funzionato per me - e sembrava il modo corretto di trasmettere informazioni via cout
Michael Vincent il

2
Se si incorporano le informazioni dalla risposta di Goz su come stampare errori / avvisi, insieme a un po 'di informazioni (purtroppo carenti dalla risposta di Goz ma presenti nei commenti sottostanti) su ciò che qDebug()ecc. Effettivamente fanno, questa sarà di gran lunga la risposta superiore (L'IMO è già superiore poiché l'OP chiede qualcosa da sostituire std::cout, ma gli elettori 40ish sembrano non essere d'accordo).
Kyle Strand

QTextStream qStdout() { return {stdout}; }potrebbe essere un modo utile per avvolgerlo, coerentemente con qWarning()ecc. E forse qualche staticstato per evitare un flusso temporaneo?
Yakk - Adam Nevraumont

36

Scrivere a stdout

Se vuoi qualcosa che, come std::cout, scrive nell'output standard della tua applicazione, puoi semplicemente fare quanto segue ( credito a CapelliC ):

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

Se vuoi evitare di creare un QTextStreamoggetto temporaneo , segui il suggerimento di Yakk nei commenti qui sotto sulla creazione di una funzione per restituire un statichandle per stdout:

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

...

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

Ricordarsi di flushflusso periodicamente per garantire la potenza viene stampata.

Scrivere a stderr

Si noti che la tecnica sopra può essere utilizzata anche per altre uscite. Tuttavia, ci sono modi più leggibili per scrivere stderr( merito a Goz e ai commenti sotto la sua risposta):

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()è chiuso se QT_NO_DEBUG_OUTPUTè attivato al momento della compilazione.

(Goz osserva in un commento che per le app non console, queste possono essere stampate su un flusso diverso rispetto a stderr.)


NOTA: tutti i metodi di stampa Qt presuppongono che gli const char*argomenti siano stringhe codificate ISO-8859-1 con \0caratteri di terminazione .


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

1
@Yakk Buon suggerimento! Incorporerò nella mia risposta.
Kyle Strand,

qFatal () riceve un errore durante la compilazione con QT5. una lettura di un post, che comunque non era (essere lì / lavoro) ... non usarlo! :)
relascope,

1
@KyleStrand Non puoi usare una funzione per quello? 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); } Usa: no_const(this).method() . Potresti iniettare quella funzione come metodo nella classe, e quindi non dovrai nemmeno passare this: Foo& no_const() const { return ::no_const(this); } nessun errore di battitura, lo prometto.
Ripristina Monica il

1
@Mitch Hm, rivedendo quei collegamenti e la documentazione di Qt, hai ragione; Non vedo nulla per indicare che c'è qualche vero problema noto causato da QTextStreamoggetti temporanei . Modificato.
Kyle Strand,

32

Aggiungi questo al tuo file di progetto:

CONFIG += console

5
Non sono state fornite informazioni sulla domanda in merito al sistema di compilazione utilizzato. Questo è rilevante solo quando si utilizza qmake.
Kyle Strand,

19

Quali variabili vuoi stampare? Se intendi QStrings, questi devono essere convertiti in c-Strings. Provare:

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

8
@CoderaPurpa Devi aggiungere#include <iostream>
Sebastian Negraszus,

myString.toUtf8().data()è migliore perché stampa personaggi al di fuori dell'intervallo ascii. Caratteri cinesi per esempio
peterchaula il

8

Ha anche una sintassi simile a prinft, ad esempio:

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

Molto utile pure


8

Vai al Progetto Properties -> Linker-> System -> SubSystem, quindi impostalo su Console(/S).


1
Questo (come la risposta di Kyle Lutz) è specifico del sistema di build.
Kyle Strand,

3

Che dire di includere la libreria iostream e precisare che cout è un oggetto di std come questo:

#include <iostream>

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

1

Se stai stampando su stderr usando la libreria stdio, una chiamata a fflush(stderr)dovrebbe svuotare il buffer e ottenere la registrazione in tempo reale.



0

Bene, dopo aver studiato diversi esempi su Internet che descrivono come inviare messaggi da una GUI in Qt a stdout, ho perfezionato un esempio autonomo funzionante sul reindirizzamento dei messaggi a una console, tramite qDebug () e l'installazione di qInstallMessageHandler (). La console verrà mostrata contemporaneamente alla GUI e può essere nascosta se ritenuto necessario. Il codice è facile da integrare con il codice esistente nel tuo progetto. Ecco l'esempio completo e sentiti libero di usarlo come preferisci, purché aderisca alla Licenza GNU GPL v2. Devi usare una forma di qualche tipo e una MainWindow penso - altrimenti il ​​campione verrà eseguito, ma probabilmente si arresterà in modo anomalo quando verrà forzato a chiudere. Nota: non c'è modo di uscire tramite un pulsante di chiusura o un menu di chiusura perché ho testato quelle alternative e l'applicazione si bloccherà alla fine ogni tanto. Senza il pulsante Chiudi l'applicazione sarà stabile e puoi chiuderla dalla finestra principale. Godere!

#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

"build & run"> Impostazione predefinita per "Esegui nel terminale" -> Abilita

per svuotare il buffer utilizzare questo comando -> fflush (stdout); puoi anche usare "\ n" in printfo cout.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.