Comment imprimer sur la console lors de l'utilisation de Qt

159

J'utilise Qt4 et C ++ pour créer des programmes en infographie. J'ai besoin de pouvoir imprimer certaines variables dans ma console au moment de l'exécution, pas de débogage, mais coutne semble pas fonctionner même si j'ajoute les bibliothèques. Y a-t-il un moyen de faire cela?

lesolorzanov
la source
3
Pouvez-vous nous dire que le cout ne fonctionne pas, car cela devrait certainement fonctionner. Obtenez-vous une erreur de compilation. Pouvez-vous montrer un exemple de code de cout qui ne fonctionne pas pour vous? Expliquez également comment vous exécutez l'application. L'exécutez-vous à partir d'une console ou à partir d'un IDE et ne voyez pas la sortie dans sa fenêtre de sortie?
Arnold Spence
Juste pour être complet: @ArnoldSpence - sans bibliothèques, j'obtiens error: ‘cout’ was not declared in this scope; avec iostream, je reçois error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char>&)(& std::cout)), ...; l'utilisation des commandes dans la réponse fonctionne plutôt bien.
sdaau
Il est difficile de proposer des solutions lorsque l'énoncé du problème est simplement «ça ne marche pas». Veuillez modifier votre question pour donner une description plus complète de ce à quoi vous vous attendiez et en quoi cela diffère des résultats réels. Voir Comment demander des conseils sur ce qui constitue une bonne explication.
Toby Speight
Dans ce cas, vous devez spécifier explicitement que ces "variables" sont des objets spécifiques à Qt (tels que QString).
user202729

Réponses:

203

S'il est suffisamment bon pour imprimer stderr, vous pouvez utiliser les flux suivants initialement destinés au débogage:

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

Bien que comme indiqué dans les commentaires, gardez à l'esprit que les messages qDebug sont supprimés si QT_NO_DEBUG_OUTPUTest défini

Si vous avez besoin de stdout, vous pouvez essayer quelque chose comme ceci (comme Kyle Strand l'a souligné):

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

Vous pouvez alors appeler comme suit:

qStdOut() << "std out!";
Goz
la source
1
J'ai demandé, sans débogage, il doit y avoir une fonction qui me permet d'écrire des messages dans la console pendant l'exécution, pas pendant le débogage.
lesolorzanov
11
Malgré son nom, cette fonction n'est pas liée au débogage avec un débogueur. C'est une fonction pratique fournie par Qt pour envoyer une sortie à stderr qui peut être supprimée de la compilation avec un define. C'est donc une alternative pour obtenir une sortie sur la console au moment de l'exécution.
Arnold Spence
Merci à tous, j'utilise ça :). Je suppose que je n'ai pas besoin d'écrire le code que j'ai utilisé. Merci! Cela a été super utile.
lesolorzanov
51
#include <QDebug>
Ducky
62
Veuillez ne pas utiliser qDebug pour toutes les sorties de la console. Utilisez-le uniquement pour de véritables impressions de débogage, utilisez qWarning, qCritical et qFatal pour les erreurs et les avertissements. Parce que les instructions qDebug peuvent être supprimées lors de la compilation avec QT_NO_DEBUG_OUTPUT pour économiser les performances et empêcher l'application d'encombrer la sortie.
JustMaximumPower
150

J'ai trouvé cela très utile:

#include <QTextStream>

QTextStream out(stdout);
foreach(QString x, strings)
    out << x << endl;
CapelliC
la source
14
Je ne sais pas pourquoi la réponse n'est pas acceptée, mais c'est certainement la plus utile.
Semyon Danilov le
4
D'accord. stderr est pour, eh bien, les erreurs (et le débogage). Cela devrait être la réponse acceptée car c'est la seule qui utilise stdout AND qt.
Marshall Eubanks
1
Celui-ci a fonctionné pour moi - et semblait être le moyen correct de sortir des informations via cout
Michael Vincent
2
Si vous intégrez les informations de la réponse de Goz sur la façon d'imprimer les erreurs / avertissements, ainsi qu'un peu d'informations (malheureusement absentes de la réponse de Goz mais présentes dans les commentaires ci-dessous) sur ce que qDebug()etc. font réellement, ce sera de loin la meilleure réponse. (OMI, c'est déjà supérieur puisque OP demande quelque chose à remplacer std::cout, mais les électeurs de 40ish semblent ne pas être d'accord).
Kyle Strand
QTextStream qStdout() { return {stdout}; }pourrait être un moyen utile pour envelopper cela, compatible avec qWarning()etc. Et peut - être un certain staticétat pour éviter streamage temporaire?
Yakk - Adam Nevraumont
36

Ecrire à stdout

Si vous voulez quelque chose qui, comme std::cout, écrit sur la sortie standard de votre application, vous pouvez simplement faire ce qui suit ( crédit à CapelliC ):

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

Si vous voulez éviter de créer un QTextStreamobjet temporaire , suivez la suggestion de Yakk dans les commentaires ci-dessous de créer une fonction pour renvoyer un statichandle pour stdout:

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

...

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

N'oubliez pas de flushconsulter régulièrement le flux pour vous assurer que la sortie est réellement imprimée.

Ecrire à stderr

Notez que la technique ci-dessus peut également être utilisée pour d'autres sorties. Cependant, il existe des moyens plus lisibles d'écrire stderr( crédit à Goz et aux commentaires sous sa réponse):

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 fermé si QT_NO_DEBUG_OUTPUTest activé au moment de la compilation.

(Goz note dans un commentaire que pour les applications non console, celles-ci peuvent s'imprimer dans un flux différent de celui stderr.)


REMARQUE: toutes les méthodes d'impression Qt supposent que les const char*arguments sont des chaînes codées ISO-8859-1 avec des \0caractères de fin .

Kyle Strand
la source
1
QTextStream qStdout() { static QTextStream r{stdout}; return r; }?
Yakk - Adam Nevraumont
1
@Yakk Bonne suggestion! Je vais intégrer dans ma réponse.
Kyle Strand
qFatal () obtient une erreur lors de la compilation avec QT5. a lu un post, que ce n'était pas ment pour (être là / travailler) de toute façon ... :)
relascope
1
@KyleStrand Vous ne pouvez pas utiliser une fonction pour cela? 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); } Utilisation: no_const(this).method() . Vous pouvez injecter cette fonction comme méthode dans la classe, et vous n'aurez même pas besoin de passer this: Foo& no_const() const { return ::no_const(this); } pas de fautes de frappe, je le promets.
Réintégrer Monica le
1
@Mitch Hm, en passant en revue ces liens et la documentation Qt, vous avez raison; Je ne vois rien qui indique qu'il existe un problème réel connu causé par des QTextStreamobjets temporaires . Édité.
Kyle Strand
32

Ajoutez ceci à votre fichier de projet:

CONFIG += console
Kyle Lutz
la source
5
Il n'y avait aucune information donnée dans la question concernant le système de construction utilisé. Ceci n'est pertinent que lors de l'utilisation qmake.
Kyle Strand
19

Quelles variables souhaitez-vous imprimer? Si vous voulez dire des QStrings, ceux-ci doivent être convertis en c-Strings. Essayer:

std::cout << myString.toAscii().data();
Sebastian Negraszus
la source
8
@CoderaPurpa Vous devez ajouter#include <iostream>
Sebastian Negraszus
myString.toUtf8().data()est mieux car il imprime les caractères en dehors de la plage ascii. Caractères chinois par exemple
peterchaula
8

Il a également une syntaxe similaire à prinft, par exemple:

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

Très pratique aussi

ulitosCoder
la source
8

Accédez au projet Properties -> Linker-> System -> SubSystem, puis réglez-le sur Console(/S).

Son Vu
la source
1
Ceci (comme la réponse de Kyle Lutz) est spécifique au système de construction.
Kyle Strand
3

Qu'en est-il d'inclure la bibliothèque iostream et de préciser que cout est un objet de std comme ceci:

#include <iostream>

std::cout << "Hello" << std::endl;
Cottet émeraude
la source
1

Si vous imprimez sur stderr à l'aide de la bibliothèque stdio, un appel à fflush(stderr)devrait vider la mémoire tampon et obtenir une journalisation en temps réel.

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

Eh bien, après avoir étudié plusieurs exemples sur Internet décrivant comment sortir des messages d'une interface graphique dans Qt vers stdout, j'ai affiné un exemple autonome de travail sur la redirection de messages vers une console, via qDebug () et l'installation de qInstallMessageHandler (). La console sera affichée en même temps que l'interface graphique et peut être masquée si nécessaire. Le code est facile à intégrer au code existant dans votre projet. Voici l'exemple complet et n'hésitez pas à l'utiliser comme vous le souhaitez, tant que vous adhérez à la licence GNU GPL v2. Vous devez utiliser une forme quelconque et une MainWindow je pense - sinon, l'exemple fonctionnera, mais se plantera probablement lorsqu'il est forcé de quitter. Remarque: il n'y a aucun moyen de quitter via un bouton de fermeture ou un menu de fermeture car j'ai testé ces alternatives et l'application finira par planter de temps en temps. Sans le bouton de fermeture, l'application sera stable et vous pourrez la fermer à partir de la fenêtre principale. Prendre plaisir!

#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();
}
user2178077
la source
0

"build & run"> Par défaut pour "Exécuter dans le terminal" -> Activer

pour vider le tampon, utilisez cette commande -> fflush (stdout); vous pouvez également utiliser "\ n" dans printfou cout.

r.shams
la source