Console output in a Qt GUI app?
Asked Answered
P

17

65

I have a Qt GUI application running on Windows that allows command-line options to be passed and under some circumstances I want to output a message to the console and then quit, for example:

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  if (someCommandLineParam)
  {
    std::cout << "Hello, world!";
    return 0;
  }

  MainWindow w;
  w.show();

  return a.exec();
}

However, the console messages do not appear when I run the app from a command-prompt. Does anyone know how I can get this to work?

Primal answered 29/7, 2010 at 8:14 Comment(4)
Are you on windows? Are you sure it's not bringing up a console and then immediately exiting it? I've never really used Qt beyond the basic tutorials thoughRecrudescence
I am on Windows and am running the app from the command-line.Primal
This actually quite a weird thing - I noticed that there is no output to the console in GUI mode, but if you run your program from commandline and redirect it to file myprogram.exe > output.txt, then output lands in this file. Perhaps something as simple as windows version of cat could easily go around the problem?Abode
Does this answer your question? How to print to console when using QtAcosmism
A
52

Windows does not really support dual mode applications.

To see console output you need to create a console application

CONFIG += console

However, if you double click on the program to start the GUI mode version then you will get a console window appearing, which is probably not what you want. To prevent the console window appearing you have to create a GUI mode application in which case you get no output in the console.

One idea may be to create a second small application which is a console application and provides the output. This can call the second one to do the work.

Or you could put all the functionality in a DLL then create two versions of the .exe file which have very simple main functions which call into the DLL. One is for the GUI and one is for the console.

Algo answered 30/7, 2010 at 8:59 Comment(4)
Yes, this is what I've come to realise - two apps!Primal
Having a small console app to call the main GUI app is fine, but is there any way to feed back the output to the console app in real time so the user can see what's going on, or to show typical output for things like -h, --version etc?Hemorrhoid
You can free the console by calling FreeConsole. So your application may decide in which mode it will work and then hide the console if running in GUI mode.Hyperbola
Be warned that FreeConsole has incredibly dangerous behaviour on Windows 8: #12676812Umbilical
P
40

Add:

#ifdef _WIN32
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
    freopen("CONOUT$", "w", stdout);
    freopen("CONOUT$", "w", stderr);
}
#endif

at the top of main(). This will enable output to the console only if the program is started in a console, and won't pop up a console window in other situations. If you want to create a console window to display messages when you run the app outside a console you can change the condition to:

if (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole())
Pediculosis answered 17/1, 2017 at 15:35 Comment(5)
This does not work for redirection (./executable > out.txt)Wolfort
I've been spending some time looking at this, and it looks like you can use GetFileType to determine if a pipe is active. In my modified code, I set stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); Then, I wrap the freopen for stdout with the conditional: if(stdout_type == FILE_TYPE_UNKNOWN) This seems to effectively allow the process to output to an existing pipe if available, but to the parent console when pipe is not open.Wolfort
This is a simple fix that worked in my case on Win7 / Qt 5.10 with a QGuiApplication that also needed console output.Richmond
IMO this should be the accepted answer as it does exactly what is asked for in the question. It also works with CMake-based Qt projects that use WIN32 in add_executable.Pieter
Don't forget to add #include <Windows.h> in your code.Freberg
E
8
void Console()
{
    AllocConsole();
    FILE *pFileCon = NULL;
    pFileCon = freopen("CONOUT$", "w", stdout);

    COORD coordInfo;
    coordInfo.X = 130;
    coordInfo.Y = 9000;

    SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coordInfo);
    SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE),ENABLE_QUICK_EDIT_MODE| ENABLE_EXTENDED_FLAGS);
}

int main(int argc, char *argv[])
{
    Console();
    std::cout<<"start@@";
    qDebug()<<"start!";

You can't use std::cout as others have said,my way is perfect even for some code can't include "qdebug" !

Elizaelizabet answered 22/12, 2013 at 19:56 Comment(3)
It does not look like you are using pFileCon. Or am I misunderstanding what the freopen does?Trichloroethylene
Neat trick for windows users. Anything cross-platform you'd recommend?Locale
Excellent solution. I would like to add that to get the Qt console behavior you need to extend the code to include stderr as well. I use it to diagnose a "Release" application installed on the client's computer. Upon a specific command line switch my Release application opens a console. With stdout and stderr rerouted to it the console outputs all of my diagnostics and Qt's errors, just like it would when you use CONFIG += console in the .pro file.Boulanger
S
7

So many answers to this topic. 0.0

So I tried it with Qt5.x from Win7 to Win10. It took me some hours to have a good working solution which doesn't produce any problems somewhere in the chain:

#include "mainwindow.h"

#include <QApplication>

#include <windows.h>
#include <stdio.h>
#include <iostream>

//
// Add to project file:
// CONFIG += console
//

int main( int argc, char *argv[] )
{
    if( argc < 2 )
    {
    #if defined( Q_OS_WIN )
        ::ShowWindow( ::GetConsoleWindow(), SW_HIDE ); //hide console window
    #endif
        QApplication a( argc, argv );
        MainWindow *w = new MainWindow;
        w->show();
        int e = a.exec();
        delete w; //needed to execute deconstructor
        exit( e ); //needed to exit the hidden console
        return e;
    }
    else
    {
        QCoreApplication a( argc, argv );
        std::string g;
        std::cout << "Enter name: ";
        std::cin >> g;
        std::cout << "Name is: " << g << std::endl;
        exit( 0 );
        return a.exec();
    }
}


I tried it also without the "CONFIG += console", but then you need to redirect the streams and create the console on your own:

#ifdef _WIN32
if (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole()){
    freopen("CONOUT$", "w", stdout);
    freopen("CONOUT$", "w", stderr);
    freopen("CONIN$", "r", stdin);
}
#endif

BUT this only works if you start it through a debugger, otherwise all inputs are directed towards the system too. Means, if you type a name via std::cin the system tries to execute the name as a command. (very strange)

Two other warnings to this attempt would be, that you can't use ::FreeConsole() it won't close it and if you start it through a console the app won't close.



Last there is a Qt help section in QApplication to this topic. I tried the example there with an application and it doesn't work for the GUI, it stucked somewhere in an endless loop and the GUI won't be rendered or it simply crashes:

QCoreApplication* createApplication(int &argc, char *argv[])
{
    for (int i = 1; i < argc; ++i)
        if (!qstrcmp(argv[i], "-no-gui"))
            return new QCoreApplication(argc, argv);
    return new QApplication(argc, argv);
}

int main(int argc, char* argv[])
{
    QScopedPointer<QCoreApplication> app(createApplication(argc, argv));

    if (qobject_cast<QApplication *>(app.data())) {
       // start GUI version...
    } else {
       // start non-GUI version...
    }

    return app->exec();
}


So if you are using Windows and Qt simply use the console option, hide the console if you need the GUI and close it via exit.

Smog answered 4/3, 2018 at 17:13 Comment(0)
J
3

No way to output a message to console when using QT += gui.

fprintf(stderr, ...) also can't print output.

Use QMessageBox instead to show the message.

Jordanson answered 29/5, 2011 at 17:5 Comment(1)
QMessageBox can output to console? o.0Locale
C
3

Oh you can Output a message when using QT += gui and CONFIG += console.

You need printf("foo bar") but cout << "foo bar" doesn't works

Cockscomb answered 4/1, 2012 at 19:13 Comment(1)
Neither printf, cout or qDebug prints anything on console in that configuration for me.Pouter
G
2

Something you may want to investigate, at least for windows, is the AllocConsole() function in the windows api. It calls GetStdHandle a few times to redirect stdout, stderr, etc. (A quick test shows this doesn't entirely do what we want it to do. You do get a console window opened alongside your other Qt stuff, but you can't output to it. Presumably, because the console window is open, there is some way to access it, get a handle to it, or access and manipulate it somehow. Here's the MSDN documentation for those interested in figuring this out:

AllocConsole(): http://msdn.microsoft.com/en-us/library/windows/desktop/ms681944%28v=vs.85%29.aspx

GetStdHandle(...): http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx

(I'd add this as a comment, but the rules prevent me from doing so...)

Gobetween answered 12/9, 2012 at 6:36 Comment(0)
E
0

I used this header below for my projects. Hope it helps.

#ifndef __DEBUG__H
#define __DEBUG__H

#include <QtGui>    

static void myMessageOutput(bool debug, QtMsgType type, const QString & msg) {

    if (!debug) return;

    QDateTime dateTime = QDateTime::currentDateTime();
    QString dateString = dateTime.toString("yyyy.MM.dd hh:mm:ss:zzz");

    switch (type) {

        case QtDebugMsg:
            fprintf(stderr, "Debug: %s\n", msg.toAscii().data());
            break;
        case QtWarningMsg:
            fprintf(stderr, "Warning: %s\n", msg.toAscii().data());
            break;
        case QtCriticalMsg:
            fprintf(stderr, "Critical: %s\n", msg.toAscii().data());
            break;
        case QtFatalMsg:
            fprintf(stderr, "Fatal: %s\n", msg.toAscii().data());
            abort();
    }
}

#endif

PS: you could add dateString to output if you want in future.

Erminiaerminie answered 29/7, 2010 at 8:32 Comment(2)
fprintf's don't produce any output in my GUI apps.Sunwise
@Sunwise Yes, output will be working only with console apps or will be showen on debugger output window in your IDEErminiaerminie
K
0

It may have been an oversight of other answers, or perhaps it is a requirement of the user to indeed need console output, but the obvious answer to me is to create a secondary window that can be shown or hidden (with a checkbox or button) that shows all messages by appending lines of text to a text box widget and use that as a console?

The benefits of such a solution are:

  • A simple solution (providing all it displays is a simple log).
  • The ability to dock the 'console' widget onto the main application window. (In Qt, anyhow).
  • The ability to create many consoles (if more than 1 thread, etc).
  • A pretty easy change from local console output to sending log over network to a client.

Hope this gives you food for thought, although I am not in any way yet qualified to postulate on how you should do this, I can imagine it is something very achievable by any one of us with a little searching / reading!

Kreis answered 8/8, 2014 at 1:51 Comment(0)
R
0

I also played with this, discovering that redirecting output worked, but I never saw output to the console window, which is present for every windows application. This is my solution so far, until I find a Qt replacement for ShowWindow and GetConsoleWindow.

Run this from a command prompt without parameters - get the window. Run from command prompt with parameters (eg. cmd aaa bbb ccc) - you get the text output on the command prompt window - just as you would expect for any Windows console app.

Please excuse the lame example - it represents about 30 minutes of tinkering.

#include "mainwindow.h"
#include <QTextStream>
#include <QCoreApplication>
#include <QApplication>
#include <QWidget>
#include <windows.h>

QT_USE_NAMESPACE

int main(int argc, char *argv[])
{
    if (argc > 1)   {
        // User has specified command-line arguments
        QCoreApplication a(argc, argv);
        QTextStream  out(stdout);
        int     i;

        ShowWindow (GetConsoleWindow(),SW_NORMAL);
        for (i=1; i<argc; i++)
             out << i << ':' << argv [i] << endl;
        out << endl << "Hello, World" << endl;
        out << "Application Directory Path:" << a.applicationDirPath() << endl;
        out << "Application File Path:" << a.applicationFilePath() << endl;
        MessageBox (0,(LPCWSTR)"Continue?",(LPCWSTR)"Silly Question",MB_YESNO);
        return 0;
    } else  {
        QApplication a(argc, argv);
        MainWindow w;

        w.setWindowTitle("Simple example");
        w.show();
        return a.exec();
    }
}
Robertoroberts answered 7/1, 2016 at 16:52 Comment(0)
S
-1

First of all, why would you need to output to console in a release mode build? Nobody will think to look there when there's a gui...

Second, qDebug is fancy :)

Third, you can try adding console to your .pro's CONFIG, it might work.

Start answered 29/7, 2010 at 9:8 Comment(2)
This application can be run in two modes - console using command-line switches amd as a GUI.Primal
Personally the console is the first place I'd look for error info :-)Ciliata
S
-1

In your .pro add

CONFIG          += console
Sapota answered 29/7, 2010 at 15:48 Comment(1)
Sorry, duplicate of what rubenvb said.Sapota
P
-1

Make sure Qt5Core.dll is in the same directory with your application executable.

I had a similar issue in Qt5 with a console application: if I start the application from Qt Creator, the output text is visible, if I open cmd.exe and start the same application there, no output is visible. Very strange!

I solved it by copying Qt5Core.dll to the directory with the application executable.

Here is my tiny console application:

#include <QCoreApplication>
#include <QDebug>

int main(int argc, char *argv[])
{
    int x=343;
    QString str("Hello World");
    qDebug()<< str << x<<"lalalaa";

    QTextStream out(stdout);
    out << "aldfjals alsdfajs...";
}
Paragraphia answered 20/8, 2015 at 14:19 Comment(0)
A
-1

After a rather long struggle with exactly the same problem I found that simply

CONFIG   += console

really does the trick. It won't work until you explicitly tell QtCreator to execute qmake on the project (right click on project) AND change something inside the source file, then rebuild. Otherwise compilation is skipped and you still won't see the output on the command line. Now my program works in both GUI and cmd line mode.

Atelectasis answered 21/7, 2016 at 7:6 Comment(1)
This was great feedback. Thanks @lemon339. Now to hide the console window that opens with the GUI.B
S
-1

One solution is to run powershell and redirect the output to whatever stream you want.

Below is an example of running powershell from cmd.exe and redirecting my_exec.exe output to both the console and an output.txt file:

powershell ".\my_exec.exe | tee output.txt"

An example (from cmd.exe) which holds open stdout/stderr and doesn't require tee or a temporary file:

my_exec.exe > NUL 2>&1
Schoof answered 15/5, 2020 at 22:24 Comment(0)
F
-2

Easy

Step1: Create new project. Go File->New File or Project --> Other Project -->Empty Project

Step2: Use the below code.

In .pro file

QT +=widgets
CONFIG += console
TARGET = minimal
SOURCES += \ main.cpp

Step3: Create main.cpp and copy the below code.

#include <QApplication>
#include <QtCore>

using namespace  std;

QTextStream in(stdin);
QTextStream out(stdout);

int main(int argc, char *argv[]){
QApplication app(argc,argv);
qDebug() << "Please enter some text over here: " << endl;
out.flush();
QString input;
input = in.readLine();
out << "The input is " << input  << endl;
return app.exec();
}

I created necessary objects in the code for your understanding.

Just Run It

If you want your program to get multiple inputs with some conditions. Then past the below code in Main.cpp

#include <QApplication>
#include <QtCore>

using namespace  std;

QTextStream in(stdin);
QTextStream out(stdout);

int main(int argc, char *argv[]){
    QApplication app(argc,argv);
    qDebug() << "Please enter some text over here: " << endl;
    out.flush();
    QString input;
    do{
        input = in.readLine();
        if(input.size()==6){
            out << "The input is " << input  << endl;   
        }
        else
        {
            qDebug("Not the exact input man");
        }
    }while(!input.size()==0);

    qDebug(" WE ARE AT THE END");

    // endif
    return app.exec();
} // end main

Hope it educates you.

Good day,

Facelifting answered 3/3, 2017 at 14:23 Comment(0)
V
-5

First of all you can try flushing the buffer

std::cout << "Hello, world!"<<std::endl;

For more Qt based logging you can try using qDebug.

Vermis answered 29/7, 2010 at 8:18 Comment(1)
std::endl doesn't make any difference BTW.Primal

© 2022 - 2024 — McMap. All rights reserved.