【发布时间】:2016-11-06 05:27:50
【问题描述】:
我已经为 QTextEdit 编写了一个包装器,以便像 QIODevice 一样使用它。我希望能够在同一个 QTextEdit 中使用多个包装器,因此我可以为每个包装器使用不同的文本颜色。
为了使这个包装器线程安全,我添加了一个 QMutex 来保护 QTextEdit 的使用。但我在想我必须只使用一个互斥锁来保护一个 QTextEdit。
我最终得到以下实现,使用 QSharedPointer 来保护 QTextEdit。
texteditiodevice.h
class TextEditIODevice : public QIODevice
{
Q_OBJECT
public:
TextEditIODevice(QTextEdit * qTextEdit, QColor color, QObject * parent);
virtual ~TextEditIODevice();
protected:
qint64 readData(char *data, qint64 maxlen);
qint64 writeData(const char *data, qint64 len);
private:
/**
* @brief Pointer to QTextEdit
*/
QPointer<QTextEdit> textEdit;
/**
* @brief Text color
*/
QColor color;
/**
* @brief Shared pointer to QTextEdit associated mutex
*/
QSharedPointer<QMutex> mutex;
/**
* @brief Storage for QTextEdit associated mutexes
*/
static QMap<QPointer<QTextEdit>, QSharedPointer<QMutex>> mutexes;
};
texteditiodevice.cpp
QMap<QPointer<QTextEdit>, QSharedPointer<QMutex>> TextEditIODevice::mutexes;
TextEditIODevice::TextEditIODevice(QTextEdit * qTextEdit, QColor color, QObject * parent) :
QIODevice(parent),
textEdit(qTextEdit),
color(color)
{
open(QIODevice::WriteOnly | QIODevice::Text);
qRegisterMetaType<QTextCharFormat>("QTextCharFormat");
qRegisterMetaType<QTextBlock>("QTextBlock");
qRegisterMetaType<QTextCursor>("QTextCursor");
if(mutexes.contains(textEdit))
mutex = mutexes[textEdit];
else
{
mutex = QSharedPointer<QMutex>(new QMutex());
mutexes.insert(textEdit, mutex);
}
}
TextEditIODevice::~TextEditIODevice()
{
}
qint64 TextEditIODevice::readData(char *data, qint64 maxlen)
{
Q_UNUSED(data);
Q_UNUSED(maxlen);
return 0;
}
qint64 TextEditIODevice::writeData(const char *data, qint64 len)
{
if(textEdit)
{
mutex->lock();
const QColor lastColor = textEdit->textColor();
textEdit->setTextColor(color);
textEdit->append(QString(data));
textEdit->setTextColor(lastColor);
mutex->unlock();
}
return len;
}
我想知道在哪里可以从mutexes 映射中删除 QSharedPointer 实例,以便删除 QMutex。
感谢您的帮助
【问题讨论】:
-
您必须重新考虑您的架构,因为您无法做到这一点。 QWidgets are not reentrant and must be used only from the main thread。解决此问题后,您将不再需要互斥锁(只有一个线程),因此问题将得到解决!
-
写入数据是在一个槽中调用的,所以是从GUI线程调用的。但是如果同时发出两个信号呢?
-
如果您的对象在主线程中并且从另一个线程发出信号,则该信号将排队等待稍后由主线程事件循环处理,因此无需使用互斥锁 :) .但是,这仅在您使用自动(默认)或排队连接连接信号时才适用。您可以查看我上面提供的链接中的“跨线程的信号和插槽”部分以获取更多信息。
标签: c++ qt qsharedpointer