【发布时间】:2015-09-27 19:59:49
【问题描述】:
在单个线程中,我有一个漂亮的类,它将所有 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;
};
但是,如果任何线程 (QThread) 是使用 cout 启动的,这将不起作用。这是因为所有的指针都搞砸了,必须使用信号和槽来允许子线程和主线程之间的数据传输。
我想修改这个类以发出信号而不是写入文本文件。这要求这个类成为一个 Q_OBJECT 并从一个继承。除了std::basic_streambuf<char> 之外,我还尝试从QObject 继承,并在正文中添加了Q_OBJECT 宏,但它没有编译。
您能帮我实现这一目标吗?我应该怎么做才能让这个类发出我可以连接并且线程安全的信号?
【问题讨论】:
-
std::cout是一个对象,进程中的所有线程共享该对象,因此“从线程中输出”没有多大意义...... -
来自非常想使用这样的东西的人:你把这个类叫做哪里?你能举例说明你是如何使用它的吗?
-
@GraemeRock 只需在事件循环或线程的构造函数中调用
logStream = new ThreadLogStream(std::cout);。这会将所有发送到std::cout的内容定向到该类。记住也要实施解决方案。这本身是行不通的。它需要QObject。 -
@the-quantum-physicist 我承认,我对代码中的所有省略号和重命名变量感到困惑。是否有可能将带有更正的原始代码作为答案发布?
-
@GraemeRock 对不起,我现在不能这样做。我非常忙。如果你直到周末才开始工作,我会发布该代码。交易?到时候告诉我。
标签: multithreading qt cout qthread