我正在嘗試使用Qt爲工作中的儀器仿真程序提供新的佈局。我們目前的sim在一個窗口中運行所有的東西(我們已經使用了glut(舊)和fltk),它使用glViewport(...)
和glScissor(...)
將儀器讀數分成它們自己的視圖,然後它使用某種形式的「ortho2D」創建自己的虛擬像素空間。模擬器當前更新儀器,然後逐個繪製各自的視口,全部在同一個線程中。是否可以將Qt GUI分割爲GUI,模擬和OpenGL的多個線程?
我們想要找到一個更好的方法,並且我們在Qt上安頓下來。我在幾大約束下工作:
- 每個儀表板仍然需要在它們的OpenGL視口中。有很多按鈕和很多樂器。我的暫時解決方案是爲每個使用QOpenGLWidget。我在這方面取得了進展。
- 這個模擬器不僅僅是一個漂亮的讀數器,還可以模擬許多儀器作爲儀器設計者的反饋,所以它有時會有很大的CPU負載。它不是一個完整的硬件仿真器,但它確實模擬了邏輯。我不認爲告訴儀器在其關聯的小部件的方法開始時更新自己是不可行的,所以我希望模擬更新在單獨的線程中運行。
- 我們的客戶可能擁有舊電腦,因此已排除更新版本的OpenGL。我們仍然使用
glBegin()
和glEnd()
以及兩者之間的所有內容,儀器繪製了一大堆變量符號,因此繪圖需要很長時間,我想將繪圖拆分到它自己的線程中。我還不知道OpenGL 3是否在桌面上,這對於渲染到離屏緩衝區是必要的(我認爲)。
問題: QOpenGLWidget不會對覆寫投放「更新」的方法,並在小部件paintEvent(...)
和paintGL(...)
電話只汲取。
暫定解:分割成模擬器三個線程:
- GUI:運行的用戶輸入,
paintEvent(...)
,和paintGL(...)
。 - 模擬器:運行所有儀器邏輯並更新符號系統的值。
- 繪圖:將最新的符號體系呈現給離線緩衝區(將使用幀緩衝區對象(FBO))。
在此設計中,跨線程交談是循環和單向的,GUI線程提供輸入,仿真器線程在下一個循環中將輸入考慮在內,繪圖線程讀取最新的符號系統和呈現它給FBO並設置「下一幀可用」標誌爲真(或可能發出信號),然後paintGL(...)
方法將採用該FBO並將其吐出到窗口小部件,從而保持事件處理和GUI響應性。繼續這個循環。
底線問題:我讀過here,GUI操作無法在單獨的線程中完成,那麼我的方法是否可行?
如果可行,任何其他謹慎或建議,將不勝感激。
通常,所有繪圖和窗口小部件操作都需要位於擁有「窗口」的線程中,這適用於普通的GUI小部件和窗口以及OpenGL。其他一切都可以在線程中。您可以修改正在繪製的對象。另一個線程中的OpenGL,只是不做另一個線程上的繪圖。另外要小心,以免修改正在繪製的對象。 –
你爲什麼需要這樣的設計? GUI系統中的事件隊列就是這樣的隊列。除非您處於專門的模式模式,否則不會錯過任何事件。這使得它非常合理,並且對於輸入延遲原因的規範,允許渲染阻止輸入處理。 –
因爲事件處理在線程上被阻塞,並且我不想將事件處理與可能持續很長時間的paintEvent(...)綁定。我的印象是,如果事件系統如此捆綁,那麼GUI可能會失去響應能力。 –