qgraphicsitem 分組比較簡單,但在分組之後 group 中的 qgraphicsitem 無法捕獲自己的相關事件(例如:滑鼠事件、鍵盤事件),實際接受消息對象為 qgraphicsitemgroup。那麼,如何處理呢?
<a href="#%e7%ae%80%e8%bf%b0">簡述</a>
<a href="#%e5%a4%84%e7%90%86%e6%96%b9%e5%bc%8f">處理方式</a>
處理方式有兩種:
方式一,也是最簡單的一種:
void qgraphicsitem::sethandleschildevents(bool enabled)
如果 enabled 為 true,qgraphicsitemgroup 将處理其所有子 item 的所有事件(即,其任何子 item 的所有事件都發送到此 item),例如:滑鼠點選子 item 的事件不會被子 item 自身處理;否則,如果 enabled 為 false,qgraphicsitemgroup 将隻處理自己的事件,不會阻止子 item 的事件,并讓子 item 處理自己的事件。
根據官方文檔描述,該函數參數的預設值為 false。經過實驗,重寫滑鼠事件、鍵盤事件之後,會發現依然會阻止子 item 的事件,究竟為何?難道是文檔有誤?
當然不會,打開 qgraphicsitemgroup 的源碼,可以發現:
在 qgraphicsitemgroup 的構造函數中就這一行代碼,也正是我們要找的答案!
是以,要讓 qgraphicsitemgroup 中的 item 處理自己的事件,還需要在構造 group 後,再手動調用:
這一行代碼即可。
方式二,
bool qgraphicsitem::sceneevent(qevent *event)
該虛函數接收到此 item 的事件。重新實作這個函數,在事件被分派到專門的事件處理程式之前攔截事件 contextmenuevent()、focusinevent()、focusoutevent()、hoverenterevent()、hovermoveevent()、hoverleaveevent()、keypressevent()、keyreleaseevent()、mousepressevent()、mousereleaseevent()、mousemoveevent()、和 mousedoubleclickevent()。
如果事件被識别和處理,則傳回 true;否則(例如,如果事件類型未被識别),則傳回 false。
event 是攔截的事件。
這樣看來,sceneevent() 接收一個 item 的所有事件,非常類似于 qwidget::event()。
既然如此,重寫此函數也可以讓 qgraphicsitemgroup 中的 item 處理自己的事件。
顯然,大多數情況下,正确的姿勢應該選擇方式一,因為對我們來說更簡單,方式二則需要為每一個自定義 item 都去實作 sceneevent()。