无法为另一个线程中的对象发送已发布的事件 - Qt
Cannot send posted events for objects in another thread - Qt
我创建了一个 QThread class 到 运行 另一个 class 中的函数,但这另一个 class 有一个指向 QWidget (QwtPlot) 的指针,我在应用程序输出中收到此消息:
QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread
我已经在另一个主题中读到 QThreads 不能与 QWidgets 一起工作(UI 小部件必须在主线程中),但我的应用程序中的输出似乎是正确的。
任何人都可以向我解释为什么会出现此消息吗?如果我让代码保持原样会发生什么?
注意:抱歉,我不会post代码。
提前致谢
I already read in another topics that QThreads doesn't work with QWidgets [...]
but the output in my application seems to be correct.
不对,不然你也不会问对不对?
A QWidget
必须在主线程中。很可能是这样。但是你是从另一个线程调用它的方法,而你调用的方法不是线程安全的。不要那样做。还有其他方法可以跨线程安全地调用方法。改用它们。例如,假设您希望调用 QWidget::resize
,您可以使用 postToThread
from this answer:
QWidget* widget;
QSize size;
Q_ASSERT_X(widget->thread() == qApp->thread(), "widget",
"The widget must live in the main thread.");
postToThread([=]{ widget->resize(size); }, widget);
如果你想要更详细,或者必须维护 Qt 4 代码库,你可以这样做:
class TSWidgetAdapter : public QObject {
Q_OBJECT
QWidget * widget() const { return qobject_cast<QWidget*>(parent()); }
Q_SLOT void resize_d(const QSize & size) { widget()->resize(size); }
public:
explicit TSWidgetAdapter(QWidget * parent) : QObject(parent) {
Q_ASSERT_X(parent->thread() == qApp->thread(), "TSWidgetAdapter()",
"The widget must live in the main thread.");
connect(this, SIGNAL(resize(QSize)), this, SLOT(resize_d(QSize)));
}
Q_SIGNAL void resize(const QSize & size);
};
QWidget* widget;
QSize size;
TSWidgetAdapter widget_ts(widget);
widget_ts.resize(size);
_d
个插槽在小部件的线程中调用。这就是自动连接的美妙之处:你可以在任何线程中调用信号,槽只会在目标对象的线程中被调用。由于适配器是小部件的子项,因此它位于小部件的线程中 - 这是由 Qt 强制执行的。
我创建了一个 QThread class 到 运行 另一个 class 中的函数,但这另一个 class 有一个指向 QWidget (QwtPlot) 的指针,我在应用程序输出中收到此消息:
QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread
我已经在另一个主题中读到 QThreads 不能与 QWidgets 一起工作(UI 小部件必须在主线程中),但我的应用程序中的输出似乎是正确的。
任何人都可以向我解释为什么会出现此消息吗?如果我让代码保持原样会发生什么?
注意:抱歉,我不会post代码。
提前致谢
I already read in another topics that QThreads doesn't work with QWidgets [...] but the output in my application seems to be correct.
不对,不然你也不会问对不对?
A QWidget
必须在主线程中。很可能是这样。但是你是从另一个线程调用它的方法,而你调用的方法不是线程安全的。不要那样做。还有其他方法可以跨线程安全地调用方法。改用它们。例如,假设您希望调用 QWidget::resize
,您可以使用 postToThread
from this answer:
QWidget* widget;
QSize size;
Q_ASSERT_X(widget->thread() == qApp->thread(), "widget",
"The widget must live in the main thread.");
postToThread([=]{ widget->resize(size); }, widget);
如果你想要更详细,或者必须维护 Qt 4 代码库,你可以这样做:
class TSWidgetAdapter : public QObject {
Q_OBJECT
QWidget * widget() const { return qobject_cast<QWidget*>(parent()); }
Q_SLOT void resize_d(const QSize & size) { widget()->resize(size); }
public:
explicit TSWidgetAdapter(QWidget * parent) : QObject(parent) {
Q_ASSERT_X(parent->thread() == qApp->thread(), "TSWidgetAdapter()",
"The widget must live in the main thread.");
connect(this, SIGNAL(resize(QSize)), this, SLOT(resize_d(QSize)));
}
Q_SIGNAL void resize(const QSize & size);
};
QWidget* widget;
QSize size;
TSWidgetAdapter widget_ts(widget);
widget_ts.resize(size);
_d
个插槽在小部件的线程中调用。这就是自动连接的美妙之处:你可以在任何线程中调用信号,槽只会在目标对象的线程中被调用。由于适配器是小部件的子项,因此它位于小部件的线程中 - 这是由 Qt 强制执行的。