Как печатать на консоль при использовании Qt


Я использую Qt4 и C++ для создания некоторых программ в компьютерной графике. Мне нужно иметь возможность печатать некоторые переменные в моей консоли во время выполнения, а не отладки, но cout не работает даже если я добавляю библиотеки. Есть ли способ сделать это?

11 132

11 ответов:

если это достаточно хорошо для печати stderr, вы можете использовать следующие потоки, первоначально предназначенные для отладки:

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

хотя, как указано в комментариях, имейте в виду, что сообщения qDebug удаляются, если QT_NO_DEBUG_OUTPUT определен

Если вам нужен stdout, вы можете попробовать что-то вроде этого (как указал Кайл Стрэнд):

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

затем вы можете позвонить следующим образом:

qStdOut() << "std out!";

нашел этой самые полезные:

#include <QTextStream>

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

добавьте это в файл проекта:

CONFIG += console

пишу stdout

если вы хотите что-то, что нравится std::cout, пишет в стандартный вывод вашего приложения, вы можете просто сделать следующее (заслуга капеллы):

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

если вы хотите избежать создания временного QTextStream объект, следуйте предложению якка в комментариях ниже о создании функции для возврата static дескриптор stdout:

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

...

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

помните to flush поток периодически для того чтобы обеспечить выход фактически напечатан.

пишу stderr

обратите внимание, что вышеописанный метод также может быть использован для других выходов. Однако есть более читаемые способы записи в stderr (кредит в ГОЗ и комментарии под его ответом):

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() закрыт, если QT_NO_DEBUG_OUTPUT включается во время компиляции.

(Goz отмечает в комментарии, что для неконсольных приложений эти может печатать в другой поток, чем stderr.)


Примечание: все методы печати Qt предположим, что const char* аргументы кодируются строки ISO-8859-1 с окончанием символы.

какие переменные вы хотите печатать? Если вы имеете в виду QStrings, они должны быть преобразованы в C-строки. Попробуйте:

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

Он также имеет синтаксис, подобный prinft, например:

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

очень удобно, а также

перейти к проекту Properties -> Linker-> System -> SubSystem, затем установите его в Console(/S).

#include <QTextStream>
...
qDebug()<<"Bla bla bla";

Как насчет включения библиотека iostream и точны, что cout объект std такой :

#include <iostream>

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

Если вы печатаете в stderr с помощью библиотеки stdio, вызовите fflush(stderr) следует очистить буфер и получить вас в режиме реального времени регистрации.

Ну, после изучения нескольких примеров в Интернете, описывающих, как выводить сообщения из графического интерфейса в Qt в stdout, я уточнил рабочий автономный пример перенаправления сообщений на консоль через qDebug() и установку qInstallMessageHandler(). Консоль будет отображаться одновременно с графическим интерфейсом и может быть скрыта, если это необходимо. Код легко интегрировать с существующим кодом в вашем проекте. Вот полный образец и не стесняйтесь использовать его в любом случае, как вам нравится, как пока вы придерживаетесь лицензии GNU GPL v2. Вы должны использовать какую - то форму и главное окно, я думаю, - иначе образец будет работать, но, вероятно, сбой при принудительном выходе. Примечание: нет никакого способа выйти с помощью кнопки закрытия или меню закрыть, потому что я проверил эти альтернативы, и приложение будет аварийно завершать работу в конечном итоге время от времени. Без кнопки закрытия приложение будет стабильным, и вы можете закрыть его из главного окна. Наслаждайтесь!

#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();
}