gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 12:55:25 25 4
gpt4 key购买 nike

在一个线程中,我有这个漂亮的类,它将所有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启动ANY线程(QThread),则此方法不起作用。这是因为所有指针都弄乱了,并且必须使用信号和插槽来允许子线程和主线程之间的数据传输。

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

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

最佳答案

推导需要先发生QObject:

class LogStream : public QObject, std::basic_streambuf<char> {
Q_OBJECT
...
};
...

如果目标是最小地修改您的代码,则有一种更简单的方法。如果您确切知道信号将插入哪个插槽,则无需继承 QObject即可发出信号。您需要做的只是以线程安全的方式调用插槽:
QMetaObject::invokeMethod(log_window, "append", Qt::QueuedConnection, 
Q_ARG(QString, tmp.c_str()));

为了加快速度,您可以缓存该方法,这样就不必每次都查找它:
class LogStream ... {
QPointer<QTextEdit> m_logWindow;
QMetaMethod m_append;

LogStream::LogStream(...) :
m_logWindow(...),
m_append(m_logWindow->metaObject()->method(
m_logWindow->metaObject()->indexOfSlot("append(QString)") )) {

...
}
};

然后,您可以更有效地调用它:
m_append.invoke(m_logWindow, Qt::QueuedConnection, Q_ARG(QString, tmp.c_str()));

最后,每当您持有生命周期不受您控制的对象的指针时,使用 QPointer会很有帮助,因为它永远不会晃动。当指向的对象被破坏时, QPointer将自己重置为0。它将至少防止您取消引用悬空指针,因为它永远不会悬空。

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

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com