How to print to console when using Qt
Asked Answered
D

12

197

I'm using Qt4 and C++ for making some programs in computer graphics. I need to be able to print some variables in my console at run-time, not debugging, but cout doesn't seem to work even if I add the libraries. Is there a way to do this?

Drayage answered 7/10, 2010 at 21:43 Comment(4)
Can you elaborate on cout not working because that should certainly work. Do you get a compile error. Can you show a code example of cout that isn't working for you? Also explain how you are running the application. Are you running it from a console or from within an IDE and not seeing output to its output window?Krystalkrystalle
Just for completeness: @ArnoldSpence - without libraries, I get error: ‘cout’ was not declared in this scope; with iostream, I get error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char>&)(& std::cout)), ...; using the commands in the answer instead works fine.Harmonist
It is difficult to offer solutions when the problem statement is simply, "it doesn't work". Please edit your question to give a more complete description of what you expected to happen and how that differs from the actual results. See How to Ask for hints on what makes a good explanation.Turnip
In this case, you should explicitly specify that those "variables" are Qt-specific objects (such as QString).Nineteenth
P
244

If it is good enough to print to stderr, you can use the following streams originally intended for debugging:

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

Though as pointed out in the comments, bear in mind qDebug messages are removed if QT_NO_DEBUG_OUTPUT is defined

If you need stdout you could try something like this (as Kyle Strand has pointed out):

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

You could then call as follows:

qStdOut() << "std out!";
Postdoctoral answered 7/10, 2010 at 21:47 Comment(7)
I asked ,while not debugging, there must be a function that allows me to write messages in console during runtime, not during debugging.Drayage
Despite its name, that function is not related to debugging with a debugger. It is a convenience function that Qt provides for sending output to stderr that can be removed from compilation with a define. So it is an alternative for achieving output to the console at runtime.Krystalkrystalle
Thank you all a lot, I'm using this :). I guess there is no need then for me to write any of the code I used. Thanks! This has been super usefull.Drayage
Please don't use qDebug for all console output. Only use it for true debug prints use qWarning, qCritical and qFatal for errors and warnings. Because qDebug statements can be removed when compiling with QT_NO_DEBUG_OUTPUT to save performance and stop the application from cluttering up the output.Stabilizer
QTextStream dooesn't flush the output, so if it used to show dynamic process, it will stall until program closesWaiter
So add an appropriate flush statement to the answer?Kilogrammeter
If you add << endl, the stream will also be flushed. This is not the case if you use "\n"Acute
R
167

I found this most useful:

#include <QTextStream>

QTextStream out(stdout);
foreach(QString x, strings)
    out << x << endl;
Reptilian answered 15/7, 2013 at 8:24 Comment(9)
Agreed. stderr is for, well, errors (and debugging). This should be the accepted answer because it's the only one which uses stdout AND qt.Patton
If you incorporate the information from Goz's answer about how to print errors/warnings, along with a bit of information (sadly lacking from Goz's answer but present in the comments below it) about what qDebug() etc actually do, this will be by far the superior answer (IMO it's already superior since OP is asking for something to replace std::cout, but 40ish voters appear not to agree).Metathesize
QTextStream qStdout() { return {stdout}; } might be a useful way to wrap this, consistent with qWarning() etc. And maybe some static state to avoid temporary streamage?Dispose
One downside of QTextStream, is it doesn't print out all the Q-Types as easily as QDebug or QInfo, etc. For example: qDebug() << widget->geometry(); v. out << widget->geometry().x() << ", " << widget->geometry().y() //....Lethargy
And should I instantiate this only once? Or can I do this per pethod?Terresaterrestrial
@TomášZato: as you like... I would probably declare an inline in a .h (maybe toStdout.h), so would be easy to callReptilian
Note that using << endl will also flush the stream, while "\n" does not.Acute
@MiB_Coder: that's by design in stdlib::streams, no ? Also, right now I don't remember if "\n" does the platform specific translation (at least on Windows, endl should be "\r\n").Reptilian
@CapelliC: As discussed in the other answers, if you write out() << "Hello\n", it will print when out is destroyed (e.g. at the end of the program), while out() << "Hello" << endl will print immediately. The c++ standard on the other hand says: endl is equivalent with "\n".Acute
T
37

Add this to your project file:

CONFIG += console
Thielen answered 8/10, 2010 at 0:58 Comment(1)
There was no information given in the question regarding which build system is being used. This is only relevant when using qmake.Metathesize
M
37

Writing to stdout

If you want something that, like std::cout, writes to your application's standard output, you can simply do the following (credit to CapelliC):

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

If you want to avoid creating a temporary QTextStream object, follow Yakk's suggestion in the comments below of creating a function to return a static handle for stdout:

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

...

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

Remember to flush the stream periodically to ensure the output is actually printed.

Writing to stderr

Note that the above technique can also be used for other outputs. However, there are more readable ways to write to stderr (credit to Goz and the comments below his answer):

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() is closed if QT_NO_DEBUG_OUTPUT is turned on at compile-time.

(Goz notes in a comment that for non-console apps, these can print to a different stream than stderr.)


NOTE: All of the Qt print methods assume that const char* arguments are ISO-8859-1 encoded strings with terminating \0 characters.

Metathesize answered 10/3, 2015 at 16:2 Comment(27)
QTextStream qStdout() { static QTextStream r{stdout}; return r; }?Dispose
@Yakk Good suggestion! I'll incorporate into my answer.Metathesize
qFatal() gets an error when compiling with QT5. a read a post, that it wasn't ment to (be there/work) anyway... don't use it! :)Viewfinder
@Viewfinder I'm not sure what you mean by "gets an error," but the documentation does indicate that it will cause a core dump on Unix, so I've indicated that in the answer.Metathesize
/* sorry, didn't find the article anymore but / qFatal("Hello Fatal"); / is the way to use it (on QT5), it send SIGABRT !!! when compiling */ qFatal() << "Hello Fatal"; / ./qfatal/main.cpp: In function 'int main(int, char*)': ../qfatal/main.cpp:13:12: error: no matching function for call to 'QMessageLogger::fatal()' qFatal() << "Hello Fatal"; [...] qlogging.h:107:10: note: candidate expects 1 argument, 0 provided */Viewfinder
@Viewfinder Ah, I see, the function itself is supposed to take the error message string. I've edited my example; all four lines now compile correctly and behave as expected.Metathesize
You don't want to be suggesting that people create a new text stream on every iteration of the loop. Even if the text stream had an optimization to make this cheap (it doesn't), it still would have very bad code smell to it. Obviously I just realized that you also comment that it's wrong. Here's what I suggest: I rolled back the edit. Sorry for the noise.Inessential
@KubaOber No problem. I actually did hope (if not assume) that since it's using an already-existing text stream in the constructor, it would have an optimization to make this cheap. But either way the "right" way to do this is indeed the function-returning-reference-to-static approach. Thanks for reminding me of this; I'll edit to simplify a bit.Metathesize
stdout is not a text stream, it's a pointer a C file object. Apart from the buffers in QTextStream, you're also at the very least constructing and destructing a temporary QIODevice every time, too. That's how a QTextStream accesses the file: by wrapping it in a QIODevice subclass (I forget which one, probably QFile).Inessential
@KubaOber Ah, that also clarifies why stdout isn't from a namespace, which I'd been wondering but hadn't looked into.Metathesize
@KyleStrand The C++98 standard, in [lib.c.files] says that stderr, stdin and stdout are macros and obviously macros can't be in any namespace. From Jakub Jelinek. That also tells you why macros are so bad, and unless you absolutely need them, they have no place in modern C++Inessential
@KyleStrand E.g. in C++ if you include <cstdio>, you can't use any symbols named stdin, stdout, stderr, in any namespace :( They behave like keywords, except that the compiler will give you weird diagnostics and/or silently miscompile your code. E.g. on OS X/clang, a public foo::stdin symbol becomes foo::__stdinp, and any code that might use it will not link iff it happens not to include <cstdio>. Global namespace pollution by macros is frightening, frankly said.Inessential
@KubaOber I actually use them quite a bit, mostly to work around what I perceive as shortcomings in the language. For instance, I have a macro that simply takes the name of a member function and creates a lambda that copy-captures this and otherwise duplicates the member function's signature. I find this easier than remembering the oddities of generic capturing in C++14 for various compilers and more readable and typesafe than using std::bind(&ClassName::functionName, this, std::placeholders::_1, .... ).Metathesize
@KyleStrand This can be done with a function, no need for a macro :)Inessential
@KubaOber If nothing else, the function would require the 'this' pointer explicitly as one of its arguments, and I believe you'd need the fully scoped name of the function with ampersand function-pointer syntax as well. That's simply not as nice as a simple macro.Metathesize
@KubaOber In other words, I find BIND_MEMBER_TO_THIS(myMemberFunc) much more readable than BindMemberToPtr(this, &MyClass::myMemberFunc).Metathesize
@KubaOber Another example that's just come up: I realize that casting away const is dangerous and should therefore be explicit, but in the case where a const member function calls a non-const member function, I find it inelegant and redundant to have to re-specify what class I'm in just to cast away const. But the syntax for inferring the type and stripping const looks like this: const_cast<std::remove_const<std::remove_reference<decltype(*this)>::type>::type&>(*this). Seriously, there is no reason to type that multiple times.Metathesize
@KyleStrand Can't you use a function for that? 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); } Use: no_const(this).method(). You could inject that function as a method into the class, and then you wouldn't even need to pass this: Foo& no_const() const { return ::no_const(this); } No typos, I promise.Inessential
@KubaOber After I wrote that, I realized that indeed the std::remove_.... functions I'm using are indeed functions, so it should be possible to write a template function that could do the rest for me. I'll admit I still think that's way more complicated than it ought to be, but it's certainly not the argument for macros that I thought it was! Thank you.Metathesize
I naively upvoted this answer before trying and I cannot take that back. But it does not work. When I replace qStdout with QTextStream(stdout) it works, so static initialization is probably a bad idea.Terresaterrestrial
@TomášZato I've tested this, so I know it works. When you say it "does not work", do you mean you get a compile error, or you don't get any output? Are you ensuring that the stream is flushed?Metathesize
It does not generate any output at all. Once I replaced it with QTextStream constructor it started working. I do not understand what do you mean by flushing the stream.Terresaterrestrial
@TomášZato Output is buffered and may not actually print until the stream is flushed (which simply means that the application forces all buffered output to be written, and stops execution until that has happened). This is done automatically by the QTextStream destructor, which may be why you're seeing output when you use the constructor directly to create temporary objects. To flush manually, just call qStdout().flush().Metathesize
@TomášZato (Buffering/flushing I/O is very standard; you should research it on your own if you still have questions about it.)Metathesize
@TomášZato I have made an edit that includes a note to flush the streams. If you are still having difficulties, feel free to remove your upvote (votes are unlocked when a post is edited).Metathesize
Is the part about making a function necessary? It seems the source you reference said it was a hypothetical: meta.#288192 I'd like to upvote this answer but I'm hesitant to believe that it's necessary to make a function that returns a static instance.Playhouse
@Playhouse Hm, reviewing those links and the Qt documentation, you're right; I don't see anything to indicate that there's any real known issue caused by temporary QTextStream objects. Edited.Metathesize
A
22

What variables do you want to print? If you mean QStrings, those need to be converted to c-Strings. Try:

std::cout << myString.toAscii().data();
Anemia answered 8/10, 2010 at 0:32 Comment(2)
@CoderaPurpa You need to add #include <iostream>Anemia
myString.toUtf8().data() is better because it prints Characters outside the ascii range. Chinese characters for exampleFeola
B
11

It also has a syntax similar to prinft, e.g.:

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

Very handy as well

Buckwheat answered 25/9, 2013 at 15:30 Comment(0)
P
7

Go the Project's Properties -> Linker-> System -> SubSystem, then set it to Console(/S).

Penthea answered 1/11, 2013 at 14:33 Comment(1)
This (like Kyle Lutz's answer) is build-system specific.Metathesize
V
5

What about including iostream library and precise that cout is an object of std like this :

#include <iostream>

std::cout << "Hello" << std::endl;
Vaporization answered 14/2, 2017 at 12:48 Comment(1)
IMHO this is the best answer. If you want to send output to Standard output just use the standard C++ iostream std::cout...Remediable
M
1

If you are printing to stderr using the stdio library, a call to fflush(stderr) should flush the buffer and get you real-time logging.

Mcroberts answered 28/3, 2014 at 18:51 Comment(0)
D
1

For Qt5 QString must be converted, for example:

QString sResultText = lblLineEdit->text(); //<--text from QLineEdit
qInfo(sResultText.toUtf8().data()); //<--show converted result
Dermis answered 13/2, 2023 at 12:28 Comment(0)
G
0

Well, after studying several examples on the Internet describing how to output messages from a GUI in Qt to stdout, I have refined a working stand-alone example on redirecting messages to a console, via qDebug() and installing qInstallMessageHandler(). The console will be showed at the same time as the GUI and can be hidden if deemed necessary. The code is easy to integrate with existing code in your project. Here is the full sample and feel free to use it in any way as you like, as long as you adhere to the License GNU GPL v2. You have to use a form of some sort and a MainWindow I think - otherwise the sample will run, but probably crash when forced to quit. Note: there is no way to quit via a close button or a menu close because I have tested those alternatives and the application will crash eventually every now and then. Without the close button the application will be stable and you can close it down from the main window. Enjoy!

#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();
}
Gstring answered 7/2, 2015 at 20:20 Comment(0)
T
0

"build & run" > Default for "Run in terminal" --> Enable

to flush the buffer use this command --> fflush(stdout); you can also use "\n" in printf or cout.

Tribunate answered 1/1, 2020 at 22:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.