2016-06-15 5 views
1

Я создал QThread класса для запуска функции, которая находится в другом классе, но это другой класс имеет указатель на QWidget (QwtPlot), и я я получать это сообщение в выходных данных приложения:Не удается отправить в курсе событий для объектов в другом потоке - Qt

QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread 

я уже читал в других темах, объекты QThread не работает с QWidgets (виджеты UI должны быть в основном потоке), но выход в моем приложении, кажется, быть верным.

Может кто-нибудь объяснить мне, почему это сообщение появляется? И что может случиться, если я дам код как есть?

Примечание: извините, я не могу опубликовать код.

Заранее спасибо

+0

Вы пытались подключить сигналы и слоты, используя ['Qt :: QueuedConnection'] (http://doc.qt.io/qt-5/qt.html#ConnectionType-enum) ?. Кроме того, вы не должны использовать указатель на QWidget. Используйте слоты и сигналы для связи виджета между потоками (опять же, без указателей). См. Пример [пример mandelbrot] (http://doc.qt.io/qt-5/qtcore-threads-mandelbrot-example.html) –

ответ

5

я уже читал в других темах, объектов QThread не работает с QWidgets [...] но выход в моем приложении кажется правильным.

Неправильно, иначе вы не спросите, не так ли?

A QWidget должно быть в основной теме. И, скорее всего, это так. Но вы вызываете его методы из другого потока, а методы, которые вы вызываете, не являются потокобезопасными. Не делай этого. Существуют и другие способы безопасного использования методов в потоках. Используйте их вместо этого. Например, предположим, что вы хотите позвонить QWidget::resize, вы могли бы использовать postToThread из 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.

 Смежные вопросы

  • Нет связанных вопросов^_^