2016-06-15 77 views
1

我創建了一個的QThread類運行一個函數,在另一個類,但是這另一個類有一個指向QWidget的(QwtPlot),和我我在應用程序的輸出接收到此消息:無法發送發佈的事件在另一個線程對象 - Qt的

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

我已經在另一個話題讀取QThreads不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

我已經在另一個話題讀取QThreads不QWidgets工作[...] 但在我的應用程序的輸出似乎是正確的。

這是不正確的,否則你不會問,對吧?

A QWidget必須在主線程中。最有可能的是。但是你從另一個線程調用它的方法,並且你調用的方法不是線程安全的。不要這樣做。還有其他方法可以跨線程安全地調用方法。改用它們。例如,假設你想打電話QWidget::resize,你可以使用postToThreadthis 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強制執行的。

相關問題