Como imprimir no console ao usar o Qt

159

Estou usando Qt4 e C ++ para fazer alguns programas em computação gráfica. Eu preciso ser capaz de imprimir algumas variáveis ​​no meu console em tempo de execução, sem depuração, mas coutparece não funcionar, mesmo se eu adicionar as bibliotecas. Existe uma maneira de fazer isso?

lesolorzanov
fonte
3
Você pode falar sobre o cout não funcionar porque isso certamente deve funcionar. Você recebe um erro de compilação. Você pode mostrar um exemplo de código do cout que não está funcionando para você? Explique também como você está executando o aplicativo. Você o está executando a partir de um console ou de um IDE e não está vendo a saída em sua janela de saída?
Arnold Spence
Apenas para completar: @ArnoldSpence - sem bibliotecas, eu entendo error: ‘cout’ was not declared in this scope; com iostream, eu entendo error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char>&)(& std::cout)), ...; usar os comandos na resposta funciona bem.
sdaau
É difícil oferecer soluções quando a declaração do problema é simplesmente "ela não funciona". Por favor edite sua pergunta para dar uma descrição mais completa do que você espera que aconteça e como que difere os resultados reais. Veja Como pedir dicas sobre o que é uma boa explicação.
precisa
Nesse caso, você deve especificar explicitamente que essas "variáveis" são objetos específicos do Qt (como QString).
user202729

Respostas:

203

Se for bom o suficiente para imprimir stderr, você poderá usar os seguintes fluxos originalmente destinados à depuração:

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

Embora, conforme indicado nos comentários, lembre-se de que as mensagens qDebug são removidas se QT_NO_DEBUG_OUTPUTdefinidas

Se você precisar do stdout, tente algo assim (como Kyle Strand apontou):

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

Você pode ligar da seguinte maneira:

qStdOut() << "std out!";
Goz
fonte
1
Perguntei, embora não depure, deve haver uma função que permita escrever mensagens no console durante o tempo de execução, não durante a depuração.
lesolorzanov
11
Apesar do nome, essa função não está relacionada à depuração com um depurador. É uma função de conveniência que o Qt fornece para enviar saída ao stderr que pode ser removida da compilação com uma definição. Portanto, é uma alternativa para obter saída para o console em tempo de execução.
Arnold Spence
Muito obrigado a todos, estou usando este :). Acho que não há necessidade de escrever nenhum código que usei. Obrigado! Isso tem sido super útil.
Leslorzanov 14/10/10
51
#include <QDebug>
ducky
62
Por favor, não use qDebug para todas as saídas do console. Use-o apenas para impressões de depuração verdadeiras, use qWarning, qCritical e qFatal para erros e avisos. Como as instruções qDebug podem ser removidas ao compilar com QT_NO_DEBUG_OUTPUT para salvar o desempenho e impedir que o aplicativo bagunce a saída.
JustMaximumPower
150

Eu achei isso mais útil:

#include <QTextStream>

QTextStream out(stdout);
foreach(QString x, strings)
    out << x << endl;
CapelliC
fonte
14
Não sei por que a resposta não é aceita, mas é a mais útil, com certeza.
Semyon Danilov 27/02
4
Acordado. stderr é para, assim, erros (e depuração). Essa deve ser a resposta aceita, porque é a única que usa stdout AND qt.
Marshall Eubanks
1
Este trabalhou para mim - e parecia ser a maneira correta de informações de saída via cout
Michael Vincent
2
Se você incorporar as informações da resposta de Goz sobre como imprimir erros / avisos, juntamente com algumas informações (infelizmente ausentes da resposta de Goz, mas presentes nos comentários abaixo) sobre o que qDebug()etc realmente fazem, essa será de longe a resposta superior (OMI já é superior, já que o OP está pedindo algo para substituir std::cout, mas os eleitores de 40 anos parecem não concordar).
Kyle Strand
QTextStream qStdout() { return {stdout}; }pode ser uma maneira útil de resolver isso, consistente com qWarning()etc. E talvez algum staticestado para evitar estrias temporárias?
Yakk - Adam Nevraumont
36

Escrevendo para stdout

Se você deseja algo que, como std::cout, grava na saída padrão do seu aplicativo, basta fazer o seguinte ( crédito ao CapelliC ):

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

Se você deseja evitar a criação de um QTextStreamobjeto temporário , siga a sugestão de Yakk nos comentários abaixo de criar uma função para retornar um staticidentificador para stdout:

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

...

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

Lembre- se flushdo fluxo periodicamente para garantir que a saída seja realmente impressa.

Escrevendo para stderr

Observe que a técnica acima também pode ser usada para outras saídas. No entanto, existem maneiras mais legíveis de escrever stderr( crédito para Goz e comentários abaixo de sua resposta):

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()está fechado se QT_NO_DEBUG_OUTPUTestiver ativado no tempo de compilação.

(Goz observa em um comentário que, para aplicativos que não são do console, eles podem ser impressos em um fluxo diferente do que stderr.)


NOTA: Todos os métodos de impressão Qt assumem que os const char*argumentos são cadeias codificadas ISO-8859-1 com \0caracteres finais .

Kyle Strand
fonte
1
QTextStream qStdout() { static QTextStream r{stdout}; return r; }?
Yakk - Adam Nevraumont
1
@Yakk Boa sugestão! Vou incorporar na minha resposta.
Kyle Strand
qFatal () obtém um erro ao compilar com o QT5. ler um post, que não era mentira (estar lá / trabalhar) de qualquer maneira ... não use! :)
relascope
1
@KyleStrand Você não pode usar uma função para isso? 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() . Você poderia injetar essa função como método na classe e nem precisaria passar this: Foo& no_const() const { return ::no_const(this); } sem erros de digitação, prometo.
Restabeleça Monica
1
@ Mitch Hm, revisando esses links e a documentação do Qt, você está certo; Não vejo nada para indicar que há algum problema real conhecido causado por QTextStreamobjetos temporários . Editado.
Kyle Strand
32

Adicione isso ao seu arquivo de projeto:

CONFIG += console
Kyle Lutz
fonte
5
Não houve informações fornecidas na pergunta sobre qual sistema de compilação está sendo usado. Isso é relevante apenas ao usar qmake.
Kyle Strand
19

Quais variáveis ​​você deseja imprimir? Se você quer dizer QStrings, eles precisam ser convertidos em c-Strings. Experimentar:

std::cout << myString.toAscii().data();
Sebastian Negraszus
fonte
8
@CoderaPurpa Você precisa adicionar ##include <iostream>
Sebastian Negraszus 16/08/2012
myString.toUtf8().data()é melhor porque imprime caracteres fora do intervalo ascii. Caracteres chineses por exemplo
peterchaula
8

Ele também possui uma sintaxe semelhante ao prinft, por exemplo:

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

Muito útil também

ulitosCoder
fonte
8

Vá para o projeto Properties -> Linker-> System -> SubSysteme defina-o Console(/S).

Son Vu
fonte
1
Isso (como a resposta de Kyle Lutz) é específico do sistema de compilação.
Kyle Strand
3

Que tal incluir a biblioteca iostream e precisar que cout é um objeto de std como este:

#include <iostream>

std::cout << "Hello" << std::endl;
Emerald Cottet
fonte
1

Se você estiver imprimindo no stderr usando a biblioteca stdio, uma chamada para fflush(stderr)deverá liberar o buffer e obter o log em tempo real.

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

Bem, depois de estudar vários exemplos na Internet que descrevem como enviar mensagens de uma GUI no Qt para o stdout, refinei um exemplo independente de trabalho para redirecionar mensagens para um console, via qDebug () e instalando qInstallMessageHandler (). O console será exibido ao mesmo tempo que a GUI e pode ser oculto, se necessário. O código é fácil de integrar com o código existente no seu projeto. Aqui está a amostra completa e fique à vontade para usá-la da maneira que quiser, desde que adira à Licença GNU GPL v2. Você tem que usar algum tipo de forma e uma MainWindow, eu acho - caso contrário, a amostra será executada, mas provavelmente trava quando forçada a sair. Nota: não há como sair por meio de um botão fechar ou de um menu fechar, porque eu testei essas alternativas e o aplicativo falhará eventualmente de vez em quando. Sem o botão Fechar, o aplicativo permanecerá estável e você poderá fechá-lo na janela principal. Aproveitar!

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

"build & run"> Padrão para "Executar no terminal" -> Ativar

para liberar o buffer, use este comando -> fflush (stdout); você também pode usar "\ n" em printfou cout.

r.shams
fonte