Qt调试信息重定向输出(qInstallMessageHandler)
由于工具需要,做了一小段Qt5测试代码,参考了网友的案例测试了以下功能
1 qDebug()重定向输出QT窗口
2 qDebug()信息保存到本地文件
QtMessageHandler qInstallMessageHandler(QtMessageHandler handler)
此函数在使用Qt消息处理程序之前已定义。返回一个指向前一个消息处理程序。
消息处理程序是一个函数,用于打印qDebug,qWarning,qCritical和qFatal的错误消息。Qt库(调试模块)包含成百上千的警告信息,打印时(通常是无效的函数参数)发生内部错误。Qt构建在release模式下还包含一些除了QT_NO_WARNING_OUTPUT和/或QT_NO_DEBUG_OUTPUT之外的警告已经设置在编译。如果你实现自己的消息处理程序,需要完全控制这些消息。
在X11或Windows下的调试器,缺省的消息处理程序向标准输出打印消息。如果这是一个致命的消息,应用程序立即中止。
只有一个消息处理程序可以被定义,因为这通常是在应用程序的基础上完成控制调试输出。
恢复消息处理程序,调用qInstallMessageHandler(0)。
注意:
QT4: qInstallMsgHandler()
QT5: qInstallMessageHandler()
参考1: https://www.cnblogs.com/wyuzm/p/9580447.html
参考2: https://blog.csdn.net/lbsljn/article/details/73804445?utm_source=blogxgwz0
TextBrower常用窗口组件说明:https://www.xuebuyuan.com/3179243.html
https://forum.qt.io/topic/68873/how-to-navigate-qplaintextedit-qtextbrowser
#include <QApplication> #include <QPointer> #include <QVariant> #include <QtCore/QVariant> #include <QDebug> QPointer<Widget> log_broswer; void outputMsg(QtMsgType type, const QMessageLogContext&, const QString& str) { log_broswer->outputMsg( type, str); } int main(int argc, char *argv[]) { QApplication a(argc, argv); log_broswer = new Widget; log_broswer->show(); qDebug() << "hello Qt"; qInstallMessageHandler(outputMsg); int result = a.exec(); delete log_broswer; return result; } #include <QWidget> #include <QCloseEvent> //#include <QDialog> #include <QDir> #include <QFileSystemWatcher> #include <QHBoxLayout> #include <QMessageBox> #include <QProcess> #include <QPushButton> #include <QTextBrowser> #include <QTimer> #include <QVBoxLayout> #include <QFileSystemWatcher> #include <QPlainTextEdit> #include <QMutex> #include <QtDebug> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); void outputMsg(QtMsgType type, const QString &msg); public slots: void start(); void save(bool enable); //path for monitor void dirUpdated(const QString &path); private slots: void on_pushButton_start_clicked(); void on_pushButton_stop_clicked(); void on_pushButton_save_clicked(); void on_pushButton_exit_clicked(); void readCmdInformation(); void autoUpdata(); void on_pushButton_update_clicked(); void displayUdiskFileList(); private: // public: Ui::Widget *ui; QTextBrowser *browser; QPlainTextEdit *plainTextEdit; QPushButton *start_button; QPushButton *stop_button; QProcess *my_process; QFileSystemWatcher *my_sysWatcher; QTimer *my_timer; bool is_finished; bool my_saveEnable; }; #endif // WIDGET_H Widget::Widget(QWidget *parent) :QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); my_timer = new QTimer(); my_process = new QProcess(); //zhi xing mingling process //if thereis output it will send out msg, receive can accept input msg connect(my_process, SIGNAL(readyRead()), this, SLOT(readCmdInformation)); my_sysWatcher = new QFileSystemWatcher(); my_sysWatcher->addPath("/data"); //monitor file path //triger when file change connect(my_sysWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(dirUpdated(QString))); is_finished = false; my_saveEnable = false; qDebug()<<" init widget "; } //read info form command line to self window void Widget::readCmdInformation() { QString str = my_process->readAllStandardOutput(); ui->plainTextEdit->appendPlainText(str); ui->plainTextEdit->moveCursor(QTextCursor::End); } //open swithch save all info to log.txt void Widget::save(bool enable) { my_saveEnable = enable; } //test scipt can remove it if necessary void Widget::start() { qDebug("start %d !" ,is_finished); for (int i = 0; i < 1000000; i++) { if (!is_finished) { QCoreApplication::processEvents(); qDebug() << QString("qDebug::").append(QString::number(i, 10)); } else { return; } } } //auto update auto exec script void Widget::autoUpdata() { ui->plainTextEdit->appendPlainText("auto update start \n"); // my_process->start("/mnt/sda1/auto.sh"); } void Widget::on_pushButton_start_clicked() { is_finished = false; qDebug()<<"start click !"; this->start(); } //show dir in u disk , need delay for mount void Widget::displayUdiskFileList() { const QDir udir("/mnt/sda1"); QStringList uDiskList = udir.entryList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files); ui->plainTextEdit->appendPlainText(QString().setNum(uDiskList.length())); for(int i =0; i<uDiskList.length();++i) { ui->plainTextEdit->appendPlainText(uDiskList[1]); } } void Widget::on_pushButton_stop_clicked() { is_finished = true; } void Widget::on_pushButton_exit_clicked() { this->close(); delete this; //key point } void Widget::on_pushButton_update_clicked() { this->autoUpdata(); } void Widget::on_pushButton_save_clicked() { this->save(true); } //get debug or warning msg void Widget::outputMsg(QtMsgType type, const QString &msg) { QString message; static QMutex mutex; mutex.lock(); switch(type) { case QtDebugMsg: message = QString("Debug:"); break; case QtWarningMsg: message = QString("Warning:"); break; case QtCriticalMsg: message = QString("Critical:"); break; case QtFatalMsg: message = QString("Fatal:"); break; } ui->plainTextEdit->appendPlainText(message.append(msg)); // qDebug()<< "go to here1\n"; ui->plainTextEdit->moveCursor(QTextCursor::End); //滑动条移动到底端 // std::cout<<"wait"; if (my_saveEnable) { QFile file("log.txt"); file.open(QIODevice::WriteOnly | QIODevice::Append); QTextStream text_stream(&file); text_stream << message << "\r\n"; file.flush(); file.close(); } mutex.unlock(); } void Widget::dirUpdated(const QString &path) { const QDir dir(path); QStringList newEntryList = dir.entryList( QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files, QDir::DirsFirst); if (newEntryList.contains("sda1")) { ui->plainTextEdit->setPlainText("U disk has been mounted"); emit my_timer->singleShot(2000, this, SLOT(displayUdiskFileList())); ui->pushButton_update->setEnabled(true); } else { ui->plainTextEdit->setPlainText("U disk has been unmounted"); ui->pushButton_update->setEnabled(false); } }