multithreading - C++ Qt : Redirect cout from a thread to emit a signal

标签 multithreading qt cout qthread

在单个线程中,我有这个漂亮的类,它将所有 cout 输出重定向到 QTextEdit

#include <iostream>
#include <streambuf>
#include <string>
#include <QScrollBar>

#include "QTextEdit"
#include "QDateTime"

class ThreadLogStream : public std::basic_streambuf<char>, QObject
{
    Q_OBJECT
public:
    ThreadLogStream(std::ostream &stream) : m_stream(stream)
    {
        m_old_buf = stream.rdbuf();
        stream.rdbuf(this);
    }
    ~ThreadLogStream()
    {
        // output anything that is left
        if (!m_string.empty())
        {
            log_window->append(m_string.c_str());
        }

        m_stream.rdbuf(m_old_buf);
    }

protected:
    virtual int_type overflow(int_type v)
    {
        if (v == '\n')
        {
            log_window->append(m_string.c_str());
            m_string.erase(m_string.begin(), m_string.end());
        }
        else
            m_string += v;

        return v;
    }


    virtual std::streamsize xsputn(const char *p, std::streamsize n)
    {
        m_string.append(p, p + n);

        long pos = 0;
        while (pos != static_cast<long>(std::string::npos))
        {
            pos = m_string.find('\n');
            if (pos != static_cast<long>(std::string::npos))
            {
                std::string tmp(m_string.begin(), m_string.begin() + pos);
                log_window->append(tmp.c_str());
                m_string.erase(m_string.begin(), m_string.begin() + pos + 1);
            }
        }

        return n;
    }

private:
    std::ostream &m_stream;
    std::streambuf *m_old_buf;
    std::string m_string;


    QTextEdit* log_window;
};

但是,如果使用 cout 启动任何线程 (QThread),则此方法不起作用。这是因为所有的指针都被搞乱了,并且必须使用信号和槽来允许子线程和主线程之间的数据传输。

我想修改此类以发出信号而不是写入文本文件。这要求此类成为 Q_OBJECT 并从其中继承。我试图继承QObject除了 std::basic_streambuf<char>并在正文中添加了 Q_OBJECT 宏,但未编译。

你能帮我实现这个目标吗?我应该怎么做才能让此类发出可以连接且线程安全的信号?

最佳答案

对于那些需要完整“有效”答案的人,这里就是。我只是复制它,因为@GraemeRock 要求它。

#ifndef ThreadLogStream_H
#define ThreadLogStream_H

#include <iostream>
#include <streambuf>
#include <string>
#include <QScrollBar>

#include "QTextEdit"
#include "QDateTime"

class ThreadLogStream : public QObject, public std::basic_streambuf<char>
{
    Q_OBJECT

public:
    ThreadLogStream(std::ostream &stream) : m_stream(stream)
    {
        m_old_buf = stream.rdbuf();
        stream.rdbuf(this);
    }
    ~ThreadLogStream()
    {
        // output anything that is left
        if (!m_string.empty())
        {
            emit sendLogString(QString::fromStdString(m_string));
        }

        m_stream.rdbuf(m_old_buf);
    }

protected:
    virtual int_type overflow(int_type v)
    {
        if (v == '\n')
        {
            emit sendLogString(QString::fromStdString(m_string));
            m_string.erase(m_string.begin(), m_string.end());
        }
        else
            m_string += v;

        return v;
    }


    virtual std::streamsize xsputn(const char *p, std::streamsize n)
    {
        m_string.append(p, p + n);

        long pos = 0;
        while (pos != static_cast<long>(std::string::npos))
        {
            pos = static_cast<long>(m_string.find('\n'));
            if (pos != static_cast<long>(std::string::npos))
            {
                std::string tmp(m_string.begin(), m_string.begin() + pos);
                emit sendLogString(QString::fromStdString(tmp));
                m_string.erase(m_string.begin(), m_string.begin() + pos + 1);
            }
        }

        return n;
    }

private:
    std::ostream &m_stream;
    std::streambuf *m_old_buf;
    std::string m_string;

signals:
    void sendLogString(const QString& str);
};


#endif // ThreadLogStream_H

关于multithreading - C++ Qt : Redirect cout from a thread to emit a signal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31317565/

相关文章:

java - JVM源码中的 'intrinsify'是什么意思?

c++ - Qt C++ 信号和槽没有触发

c++ - 用于在运行时管理多个小部件的 GUI 软件设计模式

c++ - 没有明显目标的 std::cout 留在发布的代码中是一件坏事吗?

java - 在多线程环境下制作 volatile Executor类

java - 如何将不同的值传递给 ExecutorService 中的每个线程?

java - GUI 构建后启动线程

python - 导入 OpenCV python 模块时出错(使用 Qt 和 QtOpenGL 构建时)

c++ - 当下一行出现总线错误时对 cout 感到好奇

c++ - 在 C++ 中按换行符拆分字符串