2012-04-06 76 views
9

我有一個QGraphicsScene約1000 QGraphicsItems,其實是物理項目。他們前進的每一幀,檢查碰撞,並解決其中的衝突。我真的很想擁有物理多線程。Qt物理場景多線程

我的理解是QGraphics類不是線程安全的。意思是,他們只能從主線程調用。這是否迫使我使用信號/插槽機制將每幀的最終項目屬性(x,y,旋轉)發送到主線程,然後使用主線程方法實際更新QGraphicsItems?還是有更簡單的方法來做到這一點?

以下是一個假設:我可以使用QtConcurrent在我的QGraphicsItems列表上運行一個方法嗎?如果我在我的QGraphicsItem繪畫方法中使用QMutex,並在我的物理方法中使用QMutex(這會改變我的QGraphicsItem的屬性),這是否可以保證在任何時刻只有一個線程正在讀取/寫入每個QGraphicsItem?

+0

我讀過一些關於在連接信號/插槽時使用QueuedConnection的內容。我沒有嘗試過,甚至沒有看過細節,但我認爲這值得進一步調查。有沒有其他人有這方面的經驗? – aldo 2012-04-06 05:33:45

+0

我使用了Box2D的Delphi端口,對此我非常滿意。爲什麼不試一試呢?如果您有興趣,請前往此[網頁](http://labs.qt.nokia.com/2010/02/26/qt-box2d-is-easy/)。 – menjaraz 2012-04-06 13:30:43

+0

Box2D看起來很有趣,但我沒有看到它是多線程的。 – Joel 2012-04-06 14:44:05

回答

2
  1. 如果我用我的QGraphicsItem paint方法QMutex和我 物理方法QMutex(這將改變我的QGraphicsItem的性質), 將這項保證只有一個線程讀取/寫入每個QGraphicsItem在任何時刻?

    不,它不會。 QGraphicsItem重複使用時,不僅paint方法調用。看,例如,here。即使它可以工作,這也將是一個醜陋的解決方案,因爲顯然,QGraphicsItem不僅可以用於繪畫。

  2. 這是否力我使用信號/槽機制發送的最終項目屬性(X,Y,旋轉) 每個幀到主線程,然後 使用主線程方法實際更新QGraphicsItems?或者是 有更簡單的方法來做到這一點?

    是的,您必須將項目更改過程移動到主線程。您實際上有一些替代方案:

    • 使用信號/插槽機制,如您所述。
    • 使用meta-callsQueuedConnection
    • 發送自定義事件。

    不要忘了,你有BlockingQueuedConnection,如果你想等待繪畫完成。

    此外,您可以使用所有這些東西QtConcurent

其實,也不是那麼難以管理。比手動確保線程安全性更安全,更簡單。

更大的問題是,你很可能會失敗,即使試圖閱讀項工作線程(僅使用const承包商,客人,例如)。

迄今爲止,由於QGraphicsItem不是線程安全的,所以即使讀數爲而不是。而我在Qt中多線程應用開發的經驗告訴我,如果有什麼不好的事情發生,會發生

+0

感謝您的回答。一個問題:如果我創建了一個繼承QGraphicsItem的類,並添加了一些自定義屬性(顏色,速度等),我可以從另一個線程修改它們嗎?只要我確保每次只有一個線程正在讀/寫每個屬性,我會沒事的嗎? – Joel 2012-04-09 21:01:05

+0

@Joel,如果他們不使用其他繼承的成員,你可以。但在這種情況下,我最好使用聚合而不是繼承(因爲在這種情況下,這些屬性爲一些單獨的目標提供服務,而不是實際上_extend_「QGraphicsItem」)。我個人認爲,這會增加清晰度。 – Lol4t0 2012-04-09 21:12:24

+0

我不確定聚合在我的情況下如何工作。我們很清楚,我想讓我的課程重新實現繪畫方法。我不知道如果不繼承QGraphicsItem,我會如何做到這一點。 – Joel 2012-04-09 23:27:27