将qDebug重定向到QTextEdit

sta*_*mer 4 c++ qt

我想用来qInstallMessageHandler(handler)重定向qDebugQTextEdit.

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

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

并打电话qInstallMessageHandler(redirect)给班级的顾问(蜘蛛).但是当我编译这个程序时,我收到一个错误:

不能将'Spider :: redirect'从类型'void(Spider ::)(QtMsgType,const QMessageLogContext&,const QString&)转换为'QtMessageHandler {aka void(*)(QtMsgType,const QMessageLogContext&,const QString&)}'

如果我在全局定义处理函数,那没关系.

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

phy*_*att 9

我真的很喜欢这种调试能力.在我参与的最后几个项目中,我已经完成了几次.以下是相关的代码段.

在mainwindow.h中,在你的MainWindow班级里面public

static QTextEdit * s_textEdit;
Run Code Online (Sandbox Code Playgroud)

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

QTextEdit * MainWindow::s_textEdit = 0;
Run Code Online (Sandbox Code Playgroud)

在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
Run Code Online (Sandbox Code Playgroud)

在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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

qInstallMessageHandler(myMessageOutput);
Run Code Online (Sandbox Code Playgroud)

注意:这适用于任何单线程应用程序.一旦你开始qDebug()在GUI线程之外使用,你就会崩溃.然后,您需要创建一个QueuedConnection来自任何线程函数(任何未在您的GUI线程上运行的函数),以连接到您的实例MainWindow::s_textEdit,如下所示:

QObject::connect(otherThread, SIGNAL(debug(QString)),
                 s_textEdit, SLOT(append(QString)), Qt::QueuedConnection);
Run Code Online (Sandbox Code Playgroud)

如果你最终使用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());
Run Code Online (Sandbox Code Playgroud)

希望有所帮助.


小智 1

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