以线程安全的方式调用`QQuickPaintedItem::updateImage(const QImage& image)`(无 QThread)
Calling `QQuickPaintedItem::updateImage(const QImage& image)` in a thread safe way (no QThread)
我正在阅读有关在 C++ 中创建自定义 QQuickPaintedItem
的答案
并且我想编写不依赖于 Qt 的代码。也就是说,我不想依赖QThread。我只想从 std::thread
调用 CameraView::updateImage(const QImage& image)
,而不是 q QThread
。可能吗?
我想简单地创建一个线程,将 CameraView
实例传递给它,然后从线程调用它。但是,这不是线程安全的。
如何以线程安全的方式调用 CameraView::updateImage(const QImage& image)
?
当然,您可以在代码中使用 C++ 标准库 类。例如,使用 std::mutex
更新图像如下:
void CameraView::updateImage(const QImage& image) {
std::unique_lock<std::mutex> lock(mutex); // std::mutex object is located elsewhere
// ... the rest of the code as before ...
}
您也可以保留 CameraView
代码不变,并从外部代码调用 updateImage
函数。只需确保在所有线程中使用相同的互斥体更新图像即可:
void functionInAnotherThread(CameraView& cameraView) {
std::unique_lock<std::mutex> lock(mutex); // std::mutex object is located elsewhere
// ... the rest of the code ...
cameraView.updateImage(image);
// ... the rest of the code ...
}
让我们尝试实现这种方法。让我们稍微更改一下头文件:
class CameraView : public QQuickPaintedItem {
Q_OBJECT
Q_DISABLE_COPY(CameraView)
public:
CameraView(QQuickItem* parent = nullptr);
public slots:
void updateImage(const QImage&);
void scheduleUpdate();
protected:
QImage image_;
};
现在,编写方法的定义:
void CameraView::updateImage(const QImage& image) {
image_ = image.copy(); // Does deep copy of image data.
}
void CameraView::scheduleUpdate() {
update();
}
void CameraView::paint(QPainter* painter) {
painter->drawImage(this->boundingRect(), image_);
}
最后我们写更新图片和调度重绘的函数:
void functionInAnotherThread(CameraView& cameraView) {
std::unique_lock<std::mutex> lock(mutex); // std::mutex object is located elsewhere
cameraView.updateImage(image);
lock.unlock(); // Unlock the mutex as we have already updated the image.
QMetaObject::invokeMethod(&cameraView, "scheduleUpdate",
Qt::QueuedConnection); // Call slot through the queued connection.
}
使用Qt::QueuedConnection
,当控制returns到接收者线程的事件循环时调用槽。插槽在接收方的线程中执行。因此,我们可以安排从另一个线程重绘小部件。如果这不起作用,请尝试使用其他类型的连接。
我正在阅读有关在 C++ 中创建自定义 QQuickPaintedItem
的答案
并且我想编写不依赖于 Qt 的代码。也就是说,我不想依赖QThread。我只想从 std::thread
调用 CameraView::updateImage(const QImage& image)
,而不是 q QThread
。可能吗?
我想简单地创建一个线程,将 CameraView
实例传递给它,然后从线程调用它。但是,这不是线程安全的。
如何以线程安全的方式调用 CameraView::updateImage(const QImage& image)
?
当然,您可以在代码中使用 C++ 标准库 类。例如,使用 std::mutex
更新图像如下:
void CameraView::updateImage(const QImage& image) {
std::unique_lock<std::mutex> lock(mutex); // std::mutex object is located elsewhere
// ... the rest of the code as before ...
}
您也可以保留 CameraView
代码不变,并从外部代码调用 updateImage
函数。只需确保在所有线程中使用相同的互斥体更新图像即可:
void functionInAnotherThread(CameraView& cameraView) {
std::unique_lock<std::mutex> lock(mutex); // std::mutex object is located elsewhere
// ... the rest of the code ...
cameraView.updateImage(image);
// ... the rest of the code ...
}
让我们尝试实现这种方法。让我们稍微更改一下头文件:
class CameraView : public QQuickPaintedItem {
Q_OBJECT
Q_DISABLE_COPY(CameraView)
public:
CameraView(QQuickItem* parent = nullptr);
public slots:
void updateImage(const QImage&);
void scheduleUpdate();
protected:
QImage image_;
};
现在,编写方法的定义:
void CameraView::updateImage(const QImage& image) {
image_ = image.copy(); // Does deep copy of image data.
}
void CameraView::scheduleUpdate() {
update();
}
void CameraView::paint(QPainter* painter) {
painter->drawImage(this->boundingRect(), image_);
}
最后我们写更新图片和调度重绘的函数:
void functionInAnotherThread(CameraView& cameraView) {
std::unique_lock<std::mutex> lock(mutex); // std::mutex object is located elsewhere
cameraView.updateImage(image);
lock.unlock(); // Unlock the mutex as we have already updated the image.
QMetaObject::invokeMethod(&cameraView, "scheduleUpdate",
Qt::QueuedConnection); // Call slot through the queued connection.
}
使用Qt::QueuedConnection
,当控制returns到接收者线程的事件循环时调用槽。插槽在接收方的线程中执行。因此,我们可以安排从另一个线程重绘小部件。如果这不起作用,请尝试使用其他类型的连接。