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

159

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

lesolorzanov
источник
3
Можете ли вы уточнить, что Cout не работает, потому что это, безусловно, должно работать. Вы получаете ошибку компиляции? Можете ли вы показать пример кода cout, который не работает для вас? Также объясните, как вы запускаете приложение. Вы запускаете его из консоли или из IDE и не видите вывод в его окно вывода?
Арнольд Спенс
Просто для полноты: @ArnoldSpence - без библиотек я получаю error: ‘cout’ was not declared in this scope; с iostream я получаю error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char>&)(& std::cout)), ...; использование команд в ответе вместо этого работает нормально.
Сдау
Трудно предлагать решения, когда формулировка проблемы проста: «это не работает». Пожалуйста, отредактируйте свой вопрос, чтобы дать более полное описание того, что вы ожидали, и как это отличается от фактических результатов. См. Как попросить подсказки о том, что дает хорошее объяснение.
Тоби Спейт
В этом случае вы должны явно указать, что эти «переменные» являются объектами, специфичными для Qt (например, QString).
user202729

Ответы:

204

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

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

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

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

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

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

qStdOut() << "std out!";
Goz
источник
1
Я спросил, хотя и не отлаживая, должна быть функция, которая позволяет мне писать сообщения в консоли во время выполнения, а не во время отладки.
lesolorzanov
11
Несмотря на название, эта функция не связана с отладкой с помощью отладчика. Это удобная функция, которую предоставляет Qt для отправки вывода в stderr, который можно удалить из компиляции с помощью define. Так что это альтернатива для достижения вывода на консоль во время выполнения.
Арнольд Спенс
Спасибо всем большое, я этим пользуюсь :). Я думаю, что тогда мне не нужно писать какой-либо код, который я использовал. Спасибо! Это было супер полезно.
Lesolorzanov
51
#include <QDebug>
ducky
62
Пожалуйста, не используйте qDebug для всех выводов консоли. Используйте его только для истинных отладочных отпечатков, используйте qWarning, qCritical и qFatal для ошибок и предупреждений. Потому что операторы qDebug могут быть удалены при компиляции с QT_NO_DEBUG_OUTPUT, чтобы сохранить производительность и помешать приложению загромождать вывод.
JustMaximumPower
150

Я нашел это наиболее полезным:

#include <QTextStream>

QTextStream out(stdout);
foreach(QString x, strings)
    out << x << endl;
CapelliC
источник
14
Я не знаю, почему ответ не принят, но он наверняка самый полезный.
Семен Данилов
4
Согласовано. stderr для, ну, ошибок (и отладки). Это должен быть принятый ответ, потому что он единственный, который использует stdout AND qt.
Маршалл Юбэнкс
1
Это сработало для меня - и казалось, что правильный способ вывода информации через cout
Майкл Винсент
2
Если вы включите информацию из ответа Гоза о том, как печатать ошибки / предупреждения, вместе с небольшим количеством информации (к сожалению, отсутствует в ответе Гоза, но присутствует в комментариях ниже) о том, что на qDebug()самом деле и т. Д., Это будет намного лучшим ответом (ИМО уже превосходит, так как ОП просит что-то заменить std::cout, но 40-тые избиратели, похоже, не согласны).
Кайл Стрэнд,
QTextStream qStdout() { return {stdout}; }может быть полезным способом обернуть это, в соответствии с qWarning()т. д. А может быть, какое-то staticсостояние, чтобы избежать временного распада?
Якк - Адам Невраумонт
36

Запись в stdout

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

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;

Помните , чтобы 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включено во время компиляции.

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


ПРИМЕЧАНИЕ. Все методы печати Qt предполагают, что const char*аргументами являются строки в кодировке ISO-8859-1 с завершающими \0символами.

Кайл Стрэнд
источник
1
QTextStream qStdout() { static QTextStream r{stdout}; return r; }?
Якк - Адам Невраумонт
1
@Yakk Хорошее предложение! Я включу в свой ответ.
Кайл Стрэнд,
qFatal () получает ошибку при компиляции с QT5. прочитайте пост, что это не значит (быть там / работать) в любом случае ... не используйте его! :)
relascope
1
@KyleStrand Разве вы не можете использовать функцию для этого? 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); } Использование: no_const(this).method() . Вы можете внедрить эту функцию как метод в класс, и тогда вам даже не нужно будет передавать this: Foo& no_const() const { return ::no_const(this); } никаких опечаток, обещаю.
Восстановить Монику
1
@ Mitch Hm, просматривая эти ссылки и документацию Qt, вы правы; Я не вижу ничего, что указывало бы на то, что существует какая-то реально известная проблема, вызванная временными QTextStreamобъектами. Ред.
Кайл Стрэнд
32

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

CONFIG += console
Кайл Лутц
источник
5
В вопросе не было предоставлено информации о том, какая система сборки используется. Это актуально только при использовании qmake.
Кайл Стрэнд,
19

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

std::cout << myString.toAscii().data();
Себастьян Неграсус
источник
8
@CoderaPurpa Вы ​​должны добавить#include <iostream>
Себастьян Неграсзус
myString.toUtf8().data()лучше, потому что он печатает символы вне диапазона ASCII. Например, китайские иероглифы
петерхаула
8

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

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

Также очень удобно

ulitosCoder
источник
8

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

Сон Ву
источник
1
Это (как и ответ Кайла Латса) зависит от конкретной системы сборки.
Кайл Стрэнд,
3

Как насчет включения библиотеки iostream и точного определения того, что cout является объектом std следующим образом:

#include <iostream>

std::cout << "Hello" << std::endl;
Изумрудный Коттет
источник
1

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

Эндрю Прок
источник
1
#include <QTextStream>
...
qDebug()<<"Bla bla bla";
Амир Туиту
источник
0

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

#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
источник
0

"build & run"> По умолчанию для "Запуск в терминале" -> Включить

для очистки буфера используйте эту команду -> fflush (stdout); Вы также можете использовать "\ n" в printfили cout.

r.shams
источник