Debe instalar un controlador de mensajes usando la qInstallMsgHandler
función, y luego, puede usarlo QTextStream
para escribir el mensaje de depuración en un archivo. Aquí hay un ejemplo de muestra:
#include <QtGlobal>
#include <stdio.h>
#include <stdlib.h>
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtInfoMsg:
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
abort();
}
}
int main(int argc, char **argv)
{
qInstallMessageHandler(myMessageOutput);
QApplication app(argc, argv);
...
return app.exec();
}
Tomado del documento de qInstallMsgHandler
(solo agregué los comentarios):
En el ejemplo anterior, la función myMessageOutput
utiliza stderr
lo que podría querer reemplazar con algún otro flujo de archivos, ¡o reescribir completamente la función!
Una vez que escriba e instale esta función, todos sus mensajes qDebug
(así como qWarning
, qCritical
etc.) serán redirigidos al archivo en el que está escribiendo en el controlador.
qDebug
,qWarning
,qCritical
y así sucesivamente!qInstallMsgHandler
fue desaprobado y reemplazado porqInstallMessageHandler
(la misma idea) en Qt5. Para 5.0qInstallMsgHandler
está en qt-project.org/doc/qt-5.0/qtcore/… y tambiénqInstallMessageHandler
está allí. Para 5.1,qInstallMsgHandler
se eliminó por completo.void myMessageOutput(QtMsgType type, const char *msg) { ... }
Desde aquí todo el crédito va al espíritu .
#include <QApplication> #include <QtDebug> #include <QFile> #include <QTextStream> void myMessageHandler(QtMsgType type, const QMessageLogContext &, const QString & msg) { QString txt; switch (type) { case QtDebugMsg: txt = QString("Debug: %1").arg(msg); break; case QtWarningMsg: txt = QString("Warning: %1").arg(msg); break; case QtCriticalMsg: txt = QString("Critical: %1").arg(msg); break; case QtFatalMsg: txt = QString("Fatal: %1").arg(msg); break; } QFile outFile("log"); outFile.open(QIODevice::WriteOnly | QIODevice::Append); QTextStream ts(&outFile); ts << txt << endl; } int main( int argc, char * argv[] ) { QApplication app( argc, argv ); qInstallMessageHandler(myMessageHandler); ... return app.exec(); }
fuente
qInstallMessageHandler
debe usarse en lugar deqInstallMsgHandler
cambiar el controlador de mensajes.A continuación, se muestra un ejemplo práctico de cómo conectar el controlador de mensajes predeterminado.
¡Gracias @Ross Rogers!
// -- main.cpp // Get the default Qt message handler. static const QtMessageHandler QT_DEFAULT_MESSAGE_HANDLER = qInstallMessageHandler(0); void myCustomMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { // Handle the messages! // Call the default handler. (*QT_DEFAULT_MESSAGE_HANDLER)(type, context, msg); } int main(int argc, char *argv[]) { qInstallMessageHandler(myCustomMessageHandler); QApplication a(argc, argv); qDebug() << "Wello Horld!"; return 0; }
fuente
Aquí hay una solución multiplataforma para iniciar sesión en la consola, si la aplicación se ejecutó desde Qt Creator, y en el
debug.log
archivo, cuando se compila y se ejecuta como una aplicación independiente.main.cpp :
#include <QApplication> #include <QtGlobal> #include <QtDebug> #include <QTextStream> #include <QTextCodec> #include <QLocale> #include <QTime> #include <QFile> const QString logFilePath = "debug.log"; bool logToFile = false; void customMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { QHash<QtMsgType, QString> msgLevelHash({{QtDebugMsg, "Debug"}, {QtInfoMsg, "Info"}, {QtWarningMsg, "Warning"}, {QtCriticalMsg, "Critical"}, {QtFatalMsg, "Fatal"}}); QByteArray localMsg = msg.toLocal8Bit(); QTime time = QTime::currentTime(); QString formattedTime = time.toString("hh:mm:ss.zzz"); QByteArray formattedTimeMsg = formattedTime.toLocal8Bit(); QString logLevelName = msgLevelHash[type]; QByteArray logLevelMsg = logLevelName.toLocal8Bit(); if (logToFile) { QString txt = QString("%1 %2: %3 (%4)").arg(formattedTime, logLevelName, msg, context.file); QFile outFile(logFilePath); outFile.open(QIODevice::WriteOnly | QIODevice::Append); QTextStream ts(&outFile); ts << txt << endl; outFile.close(); } else { fprintf(stderr, "%s %s: %s (%s:%u, %s)\n", formattedTimeMsg.constData(), logLevelMsg.constData(), localMsg.constData(), context.file, context.line, context.function); fflush(stderr); } if (type == QtFatalMsg) abort(); } int main(int argc, char *argv[]) { QByteArray envVar = qgetenv("QTDIR"); // check if the app is ran in Qt Creator if (envVar.isEmpty()) logToFile = true; qInstallMessageHandler(customMessageOutput); // custom message handler for debugging QApplication a(argc, argv); // ...and the rest of 'main' follows
El formato del registro lo manejan
QString("%1 %2: %3 (%4)").arg...
(para el archivo) yfprintf(stderr, "%s %s: %s (%s:%u, %s)\n"...
(para la consola).Inspiración: https://gist.github.com/polovik/10714049 .
fuente
Bueno, yo diría que el momento en que necesita redirigir su salida de depuración a algo diferente a stderr es cuando podría pensar en alguna herramienta de registro. Si cree que necesita uno, le recomendaría usar
QxtLogger
( "La clase QxtLogger es una herramienta de registro fácil de usar y fácil de ampliar" ) de laQxt
biblioteca.fuente
Aquí hay un ejemplo de Qt idiomático simple y seguro para subprocesos para iniciar sesión
stderr
y archivar:Instálelo
qInstallMessageHandler(messageHandler)
como se describe en otras respuestas.fuente