【问题标题】:redirect qDebug to QTextEdit将 qDebug 重定向到 QTextEdit
【发布时间】:2014-03-18 16:22:58
【问题描述】:

我想使用qInstallMessageHandler(handler)qDebug 重定向到QTextEdit

我在一个类中定义了一个处理函数:

void Spider::redirect(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
    console->append(msg);
}

并在类(Spider)的构造函数中调用qInstallMessageHandler(redirect)

但是,当我编译这个程序时,我得到了一个错误:

无法从“void”类型转换“Spider::redirect” (Spider::)(QtMsgType, const QMessageLogContext&, const QString&)' 到 type 'QtMessageHandler {aka void (*)(QtMsgType, const QMessageLogContext&, const QString&)}'

如果我在全局中定义处理函数,就可以了。

我无法弄清楚这两种行为之间的区别。

【问题讨论】:

    标签: c++ qt


    【解决方案1】:

    我真的很喜欢这种调试能力。在我从事的最后几个项目中,我已经完成了几次。以下是相关代码sn-ps。

    在 mainwindow.h 中,在 MainWindow 类中,在 public

    static QTextEdit * s_textEdit;
    

    在 mainwindow.cpp 中,在任何函数之外

    QTextEdit * MainWindow::s_textEdit = 0;
    

    在 MainWindow 构造函数中

    s_textEdit = new QTextEdit;
    // be sure to add the text edit into the GUI somewhere, 
    // like in a layout or on a tab widget, or in a dock widget
    

    在main.cpp中,main()上方

    void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
    {
        if(MainWindow::s_textEdit == 0)
        {
            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 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();
            }
        }
        else
        {
            switch (type) {
            case QtDebugMsg:
            case QtWarningMsg:
            case QtCriticalMsg:
                // redundant check, could be removed, or the 
                // upper if statement could be removed
                if(MainWindow::s_textEdit != 0)
                    MainWindow::s_textEdit->append(msg);
                break;
            case QtFatalMsg:
                abort();
            }
        }
    }
    

    在 main.cpp 中的 main() 中,在初始化 QApplication 实例之前。

    qInstallMessageHandler(myMessageOutput);
    

    注意:这对任何单线程应用程序都非常有效。一旦你开始在你的 GUI 线程外使用qDebug(),你就会崩溃。然后,您需要从任何线程函数(任何不在您的 GUI 线程上运行的函数)创建一个 QueuedConnection,以连接到您的 MainWindow::s_textEdit 实例,如下所示:

    QObject::connect(otherThread, SIGNAL(debug(QString)),
                     s_textEdit, SLOT(append(QString)), Qt::QueuedConnection);
    

    如果您最终使用QDockWidgets 并使用QMenu,您还可以做一些其他很酷的事情。最终结果是一个非常用户友好、易于管理的控制台窗口。

    QMenu * menu;
    menu = this->menuBar()->addMenu("About");
    menu->setObjectName(menu->title());
    
    // later on...
    
    QDockWidget *dock;
    dock = new QDockWidget("Console", this);
    dock->setObjectName(dock->windowTitle());
    dock->setWidget(s_textEdit);
    s_textEdit->setReadOnly(true);
    this->addDockWidget(Qt::RightDockWidgetArea, dock);
    this->findChild<QMenu*>("About")->addAction(dock->toggleViewAction());
    

    希望对您有所帮助。

    【讨论】:

      【解决方案2】:

      非静态类方法和全局函数有不同的签名。您不能将非静态方法用作函数。

      【讨论】:

      • 拒绝投票,因为这没有回答“如何将 qDebug 重定向到 QTextEdit”的问题。这个答案解释了为什么提问者会收到错误而不是如何解决提问者的问题
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-23
      • 1970-01-01
      • 2014-01-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多