Drucken auf der Konsole bei Verwendung von Qt

159

Ich benutze Qt4 und C ++, um einige Programme in Computergrafik zu erstellen. Ich muss in der Lage sein, einige Variablen zur Laufzeit in meiner Konsole zu drucken, nicht zu debuggen, aber es coutscheint nicht zu funktionieren, selbst wenn ich die Bibliotheken hinzufüge. Gibt es eine Möglichkeit, dies zu tun?

lesolorzanov
quelle
3
Können Sie näher darauf eingehen, dass Cout nicht funktioniert, weil das auf jeden Fall funktionieren sollte? Erhalten Sie einen Kompilierungsfehler? Können Sie ein Codebeispiel für cout zeigen, das für Sie nicht funktioniert? Erklären Sie auch, wie Sie die Anwendung ausführen. Führen Sie es von einer Konsole oder innerhalb einer IDE aus und sehen Sie keine Ausgabe in ihrem Ausgabefenster?
Arnold Spence
Nur der Vollständigkeit halber: @ArnoldSpence - ohne Bibliotheken bekomme ich error: ‘cout’ was not declared in this scope; mit iostream bekomme ich error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char>&)(& std::cout)), ...; Die Verwendung der Befehle in der Antwort funktioniert stattdessen einwandfrei.
Sdaau
Es ist schwierig, Lösungen anzubieten, wenn die Problemstellung einfach lautet: "Es funktioniert nicht". Bitte bearbeiten Sie Ihre Frage, um eine vollständigere Beschreibung dessen zu erhalten, was Sie erwartet haben und wie sich dies von den tatsächlichen Ergebnissen unterscheidet. Siehe So fragen Sie nach Hinweisen, was eine gute Erklärung ausmacht.
Toby Speight
In diesem Fall sollten Sie explizit angeben, dass diese "Variablen" Qt-spezifische Objekte sind (z. B. QString).
user202729

Antworten:

203

Wenn es zum Drucken gut genug ist stderr, können Sie die folgenden Streams verwenden, die ursprünglich zum Debuggen vorgesehen waren:

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

Beachten Sie jedoch, dass qDebug-Nachrichten entfernt werden, wenn dies QT_NO_DEBUG_OUTPUTdefiniert ist

Wenn Sie Standard benötigen, können Sie so etwas ausprobieren (wie Kyle Strand betont hat):

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

Sie können dann wie folgt anrufen:

qStdOut() << "std out!";
Goz
quelle
1
Ich fragte, während ich nicht debugge, muss es eine Funktion geben, die es mir ermöglicht, Nachrichten zur Laufzeit in die Konsole zu schreiben, nicht während des Debuggens.
Lesolorzanov
11
Trotz ihres Namens bezieht sich diese Funktion nicht auf das Debuggen mit einem Debugger. Es ist eine praktische Funktion, die Qt zum Senden von Ausgaben an stderr bereitstellt, die mit einer Definition aus der Kompilierung entfernt werden können. Es ist also eine Alternative, um zur Laufzeit eine Ausgabe an die Konsole zu erzielen.
Arnold Spence
Vielen Dank, ich benutze das :). Dann muss ich wohl keinen der von mir verwendeten Codes schreiben. Vielen Dank! Das war super nützlich.
Lesolorzanov
51
#include <QDebug>
ducky
62
Bitte verwenden Sie qDebug nicht für alle Konsolenausgaben. Verwenden Sie es nur für echte Debug-Ausdrucke. Verwenden Sie qWarning, qCritical und qFatal für Fehler und Warnungen. Weil qDebug-Anweisungen beim Kompilieren mit QT_NO_DEBUG_OUTPUT entfernt werden können, um Leistung zu sparen und die Anwendung daran zu hindern, die Ausgabe zu überladen.
JustMaximumPower
150

Ich fand das am nützlichsten:

#include <QTextStream>

QTextStream out(stdout);
foreach(QString x, strings)
    out << x << endl;
CapelliC
quelle
14
Ich weiß nicht, warum eine Antwort nicht akzeptiert wird, aber sie ist mit Sicherheit die nützlichste.
Semyon Danilov
4
Einverstanden. stderr ist für Fehler (und Debugging). Dies sollte die akzeptierte Antwort sein, da dies die einzige ist, die stdout AND qt verwendet.
Marshall Eubanks
1
Dieser funktionierte für mich - und schien der richtige Weg zu sein, um Informationen über cout auszugeben
Michael Vincent
2
Wenn Sie die Informationen aus Goz 'Antwort zum Drucken von Fehlern / Warnungen zusammen mit einigen Informationen (die leider in Goz' Antwort fehlen, aber in den Kommentaren darunter enthalten sind) darüber qDebug()einbeziehen, was usw. tatsächlich tun, ist dies bei weitem die überlegene Antwort (IMO ist es bereits überlegen, da OP um Ersatz bittet std::cout, aber 40-jährige Wähler scheinen nicht zuzustimmen).
Kyle Strand
QTextStream qStdout() { return {stdout}; }könnte ein nützlicher Weg sein, dies zu verpacken, im Einklang mit qWarning()usw. Und vielleicht ein staticZustand, um vorübergehendes Streaming zu vermeiden?
Yakk - Adam Nevraumont
36

Schreiben an stdout

Wenn Sie etwas möchten, das beispielsweise std::coutin die Standardausgabe Ihrer Anwendung schreibt, können Sie einfach Folgendes tun ( Gutschrift an CapelliC ):

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

Wenn Sie ein temporäres Erstellung vermeiden wollen QTextStreamObjekt, folgt einen zurückzukehren Yakk Vorschlag in den Kommentaren unten von einer Funktion zu schaffen staticfür Griff stdout:

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

...

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

Denken Sieflush regelmäßig an den Stream, um sicherzustellen, dass die Ausgabe tatsächlich gedruckt wird.

Schreiben an stderr

Beachten Sie, dass die obige Technik auch für andere Ausgänge verwendet werden kann. Es gibt jedoch besser lesbare Möglichkeiten zum Schreiben stderr( Dank an Goz und die Kommentare unter seiner Antwort):

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()wird geschlossen, wenn QT_NO_DEBUG_OUTPUTes zur Kompilierungszeit aktiviert ist.

(Goz stellt in einem Kommentar fest, dass Apps ohne Konsole in einem anderen Stream als gedruckt werden können stderr.)


HINWEIS: allen Qt-Druckmethoden wird davon ausgegangen, dass es sich bei den const char*Argumenten um ISO-8859-1-codierte Zeichenfolgen mit Abschlusszeichen handelt \0.

Kyle Strand
quelle
1
QTextStream qStdout() { static QTextStream r{stdout}; return r; }?
Yakk - Adam Nevraumont
1
@ Yakk Guter Vorschlag! Ich werde in meine Antwort einbeziehen.
Kyle Strand
qFatal () erhält beim Kompilieren mit QT5 einen Fehler. a einen Beitrag lesen, den es sowieso nicht erwähnen sollte (da sein / arbeiten) ... benutze ihn nicht! :)
Relascope
1
@KyleStrand Kannst du dafür keine Funktion verwenden? 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); } Verwenden Sie : no_const(this).method() . Sie könnten diese Funktion als Methode in die Klasse einfügen, und dann müssten Sie nicht einmal übergeben this: Foo& no_const() const { return ::no_const(this); } Keine Tippfehler, das verspreche ich.
Stellen Sie Monica am
1
@Mitch Hm, wenn Sie diese Links und die Qt-Dokumentation überprüfen, haben Sie Recht. Ich sehe nichts, was darauf hindeutet, dass es ein wirklich bekanntes Problem gibt, das durch temporäre QTextStreamObjekte verursacht wird . Bearbeitet.
Kyle Strand
32

Fügen Sie dies Ihrer Projektdatei hinzu:

CONFIG += console
Kyle Lutz
quelle
5
In der Frage, welches Build-System verwendet wird, wurden keine Informationen angegeben. Dies ist nur bei Verwendung relevant qmake.
Kyle Strand
19

Welche Variablen möchten Sie drucken? Wenn Sie QStrings meinen, müssen diese in c-Strings konvertiert werden. Versuchen:

std::cout << myString.toAscii().data();
Sebastian Negraszus
quelle
8
@CoderaPurpa Sie müssen hinzufügen#include <iostream>
Sebastian Negraszus
myString.toUtf8().data()ist besser, weil Zeichen außerhalb des ASCII-Bereichs gedruckt werden. Chinesische Schriftzeichen zum Beispiel
Peterchaula
8

Es hat auch eine Syntax ähnlich wie prinft, zB:

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

Sehr praktisch

ulitosCoder
quelle
8

Gehen Sie zu den Projekten und Properties -> Linker-> System -> SubSystemsetzen Sie sie auf Console(/S).

Sohn Vu
quelle
1
Dies ist (wie Kyle Lutz 'Antwort) Build-System-spezifisch.
Kyle Strand
3

Was ist mit der Aufnahme der iostream-Bibliothek und der genauen Feststellung, dass cout ein Objekt von std wie diesem ist:

#include <iostream>

std::cout << "Hello" << std::endl;
Smaragd Cottage
quelle
1

Wenn Sie mit der stdio-Bibliothek auf stderr drucken, sollte ein Aufruf von fflush(stderr)den Puffer leeren und Sie in Echtzeit protokollieren.

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

Nachdem ich einige Beispiele im Internet studiert habe, die beschreiben, wie Nachrichten von einer GUI in Qt an stdout ausgegeben werden, habe ich ein eigenständiges Beispiel für die Umleitung von Nachrichten an eine Konsole über qDebug () und die Installation von qInstallMessageHandler () verfeinert. Die Konsole wird gleichzeitig mit der GUI angezeigt und kann bei Bedarf ausgeblendet werden. Der Code lässt sich leicht in vorhandenen Code in Ihr Projekt integrieren. Hier ist das vollständige Beispiel und Sie können es beliebig verwenden, solange Sie die Lizenz GNU GPL v2 einhalten. Sie müssen eine Form und ein MainWindow verwenden, denke ich - sonst wird das Beispiel ausgeführt, stürzt aber wahrscheinlich ab, wenn es zum Beenden gezwungen wird. Hinweis: Es gibt keine Möglichkeit, über eine Schaltfläche zum Schließen oder ein Schließen des Menüs zu beenden, da ich diese Alternativen getestet habe und die Anwendung von Zeit zu Zeit abstürzt. Ohne die Schaltfläche zum Schließen ist die Anwendung stabil und Sie können sie über das Hauptfenster schließen. Genießen!

#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
quelle
0

"build & run"> Standard für "Run in terminal" -> Enable

Um den Puffer zu leeren, verwenden Sie diesen Befehl -> fflush (stdout); Sie können auch "\ n" in printfoder verwenden cout.

r.shams
quelle