Debe instalar un controlador de mensajes usando la qInstallMsgHandlerfunción, y luego, puede usarlo QTextStreampara 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 myMessageOutpututiliza stderrlo 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, qCriticaletc.) serán redirigidos al archivo en el que está escribiendo en el controlador.
qDebug,qWarning,qCriticaly así sucesivamente!qInstallMsgHandlerfue desaprobado y reemplazado porqInstallMessageHandler(la misma idea) en Qt5. Para 5.0qInstallMsgHandlerestá en qt-project.org/doc/qt-5.0/qtcore/… y tambiénqInstallMessageHandlerestá allí. Para 5.1,qInstallMsgHandlerse 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
qInstallMessageHandlerdebe usarse en lugar deqInstallMsgHandlercambiar 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.logarchivo, 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' followsEl 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 laQxtbiblioteca.fuente
Aquí hay un ejemplo de Qt idiomático simple y seguro para subprocesos para iniciar sesión
stderry archivar:void messageHandler (tipo QtMsgType, const QMessageLogContext & context, const QString & message) { mutex estático de QMutex; Bloqueo de QMutexLocker (& mutex); Archivo de registro de QFile estático (LOGFILE_LOCATION); static bool logFileIsOpen = logFile.open (QIODevice :: Append | QIODevice :: Text); std :: cerr << qPrintable (qFormatLogMessage (tipo, contexto, mensaje)) << std :: endl; if (logFileIsOpen) { logFile.write (qFormatLogMessage (tipo, contexto, mensaje) .toUtf8 () + '\ n'); logFile.flush (); } }Instálelo
qInstallMessageHandler(messageHandler)como se describe en otras respuestas.fuente