J'utilise Qt4 et C++ pour créer des programmes en infographie. Je dois pouvoir imprimer certaines variables dans ma console au moment de l'exécution, sans déboguer, mais cout
ne semble pas fonctionner même si j'ajoute les bibliothèques. Y a-t-il un moyen de faire cela?
S'il est suffisant d'imprimer sur stderr
, vous pouvez utiliser les flux suivants initialement destinés au débogage:
#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" );
Cependant, comme indiqué dans les commentaires, gardez à l'esprit que les messages qDebug sont supprimés si QT_NO_DEBUG_OUTPUT
est défini
Si vous avez besoin de stdout, vous pouvez essayer quelque chose comme ceci (comme l'a souligné Kyle Strand):
QTextStream& qStdOut()
{
static QTextStream ts( stdout );
return ts;
}
Vous pouvez alors appeler comme suit:
qStdOut() << "std out!";
J'ai trouvé this plus utile:
#include <QTextStream>
QTextStream out(stdout);
foreach(QString x, strings)
out << x << endl;
stdout
Si vous voulez quelque chose qui, comme std::cout
, soit écrit sur la sortie standard de votre application, vous pouvez simplement faire ce qui suit ( crédit à CapelliC ):
QTextStream(stdout) << "string to print" << endl;
Si vous voulez éviter de créer un objet temporaire QTextStream
, suivez la suggestion de Yakk dans les commentaires ci-dessous de créer une fonction pour renvoyer un handle static
pour stdout
:
inline QTextStream& qStdout()
{
static QTextStream r{stdout};
return r;
}
...
foreach(QString x, strings)
qStdout() << x << endl;
N'oubliez pas à flush
le flux périodiquement pour vous assurer que le résultat est réellement imprimé.
stderr
Notez que la technique ci-dessus peut également être utilisée pour d'autres sorties. Cependant, il existe des moyens plus lisibles d'écrire dans stderr
( crédit à Goz et les commentaires sous sa réponse):
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 fermé si QT_NO_DEBUG_OUTPUT
est activé à la compilation.
(Dans un commentaire, Goz note que, pour les applications non-console, celles-ci peuvent être imprimées dans un flux différent de stderr
.)
REMARQUE: Toutes les méthodes d'impression Qt supposons que const char*
arguments sont des chaînes codées ISO-8859-1 avec mettre fin à \0
caractères.
Ajoutez ceci à votre fichier de projet:
CONFIG += console
Quelles variables voulez-vous imprimer? Si vous voulez parler de QStrings, ceux-ci doivent être convertis en c-Strings. Essayer:
std::cout << myString.toAscii().data();
Allez dans le Properties -> Linker-> System -> SubSystem
du projet, puis réglez-le sur Console(/S)
.
Il a également une syntaxe similaire à prinft, par exemple:
qDebug ("message %d, says: %s",num,str);
Très pratique aussi
Pourquoi ne pas inclure la bibliothèque iostream et préciser que cout est un objet de std comme ceci:
#include <iostream>
std::cout << "Hello" << std::endl;
#include <QTextStream>
...
qDebug()<<"Bla bla bla";
Si vous imprimez sur stderr à l'aide de la bibliothèque stdio, un appel à fflush(stderr)
devrait vider la mémoire tampon et obtenir une journalisation en temps réel.
Eh bien, après avoir étudié plusieurs exemples sur Internet décrivant comment sortir des messages d'une interface utilisateur graphique dans Qt sur stdout, j'ai affiné un exemple autonome sur la redirection de messages vers une console, via qDebug () et l'installation de qInstallMessageHandler (). La console sera affichée en même temps que l'interface graphique et peut être masquée si nécessaire. Le code est facile à intégrer au code existant dans votre projet. Voici l'échantillon complet et n'hésitez pas à l'utiliser à votre guise, tant que vous respectez la Licence GNU GPL v2. Vous devez utiliser une forme quelconque et une fenêtre principale, je pense, sinon l'échantillon s'exécutera, mais se plantera probablement lorsqu'il sera forcé de quitter. Remarque: il n'y a aucun moyen de quitter via un bouton de fermeture ou une fermeture de menu car j'ai testé ces alternatives et l'application se plantera éventuellement de temps en temps. Sans le bouton de fermeture, l'application sera stable et vous pourrez la fermer à partir de la fenêtre principale. Prendre plaisir!
#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();
}