2010-03-04 197 views
9

我有一個後臺線程和線程調用更新UI的一些方法(以顯示進度條並顯示文本區域中的其他信息)。Qt:後臺線程刷新UI線程

如果我修改了某些UI小部件值,則會發出「無法將事件發送給由不同線程擁有的對象」斷言錯誤。

看看論壇,我讀到我可以使用QMetaObject :: invokeMethod方法,但它只是工作,如果我通過它的Qt :: DirectConnection標誌,實際上引發上述相同的錯誤。

如果我使用Qt :: QueuedConnection或Qt :: AutoConnection,則invokeMethod返回false。

我的代碼看起來與此類似:

.H:

class A : public QMainWindow 
{ 
    Q_OBJECT 

    QProgressBar* pb; 

    public slots: 
    bool m(bool, int); 
}; 

class B 
{ 
    A* a; 

    public: 
    void handleEvent(); 
}; 


.cpp: 

bool A::m(bool x, int y) 
{ 
    pb->setValue(y); 
    return x; 
} 

void B::handleEvent() 
{ 
    //a->m(true, 12); //raises an assertion error 

    bool r; 
    //bool ret = QMetaObject::invokeMethod(a, "m", Qt::DirectConnection, Q_RETURN_ARG(bool, r), Q_ARG(bool, true), Q_ARG(int, 12)); //raises the same assertion error error 

    bool ret = QMetaObject::invokeMethod(a, "m", Qt::AutoConnection, Q_RETURN_ARG(bool, r), Q_ARG(bool, true), Q_ARG(int, 12)); //is ignored and ret contains false. 
} 

你知道是怎麼回事,或者我做錯了嗎?或者,也許,有人可以建議我另一種方法來處理我的新手問題?

由於提前,

埃內斯托

回答

10

我沒有用invokeMethod()自己,但要做到這一點,我通常只使用信號和槽。例如,你可以創建一個信號的class B成員連接到插槽中class A,更新的進展:

class B : public QObject 
{ 
    Q_OBJECT 

    A* a; 

signals: 
    void update_signal(bool, int); 

public: 
    void handleEvent(); 
}; 

B::B() 
{ 
    //assuming a already points to the correct place... 
    connect(this, SIGNAL(update_signal(bool,int), 
      a, SLOT(m(bool,int)), Qt::QueuedConnection); 
} 

void B::handleEvent() 
{ 
    emit update_signal(true, 12); 
} 

A::m()將不得不在這種情況下,返回void而不是因爲當一個問題使用排隊連接,由於調用是異步的,因此無法得到返回值(在調用插槽函數之前emit update_signal(true,12)可能會返回,因此無法準備好返回值)。

只要您有指向類型爲A的對象和類型爲B的對象的指針,您實際上可以在任何位置執行此連接。這使得信號和插槽非常靈活,因爲您可以從B完全解耦A,但仍允許它們通過信號和插槽進行通信。例如:

class B : public QObject 
{ 
    Q_OBJECT 

signals: 
    void update_signal(bool, int); 

public: 
    void handleEvent(); 
}; 

void B::handleEvent() 
{ 
    emit update_signal(true, 12); 
} 

class A : public QMainWindow 
{ 
    Q_OBJECT 

    QProgressBar* pb; 

    public slots: 
     void m(bool, int); 
}; 

void A::m(bool x, int y) 
{ 
    pb->setValue(y); 
} 

int main() 
{ 
    A* a = new A(); 
    B* b = new B(); 

    QObject::connect(b, SIGNAL(update_signal(bool, int)), 
      a, SLOT(m(bool, int)), Qt::QueuedConnection); 

    //... 
} 

在這種情況下,b不必存儲指針或瞭解a任何事情,他們可以通過薄定義良好的溝通渠道。