<div dir="ltr"><div><div><div>Hi Phil,<br></div><div><br>In sip/QtWidgets/qgraphicssceneevent.sip, the interface for QGraphicsSceneEvent can be seen to expose a private API function (QGraphicsSceneEvent.setWidget). The similar private member functions for setting the scenePos and related attributes of QGraphicsScene*Event objects are not exposed, however. These would be very useful for allowing interaction with QGraphicsItems from another scene that are painted into a QGraphicsView derivative's viewport by calling QGraphicsScene.render(..) in the QGraphicsView derivative's drawForeground function.<br><br></div>For example (working example!):<br><br>
<div style="color:rgb(0,0,0);background-color:rgb(245,245,245);font-style:normal;font-weight:normal;text-decoration:none">
<pre><span style="color:rgb(128,0,128)">from</span><span> </span><span>PyQt5</span><span> </span><span style="color:rgb(128,0,128)">import</span><span> </span><span>Qt</span>
<span style="color:rgb(128,0,128)">class</span><span> </span><span style="color:rgb(0,0,176)">OverlayGS</span><span>(</span><span>Qt</span><span>.</span><span>QGraphicsScene</span><span>):</span>
<span> </span><span style="color:rgb(128,0,128)">def</span><span> </span><span style="color:rgb(0,0,255)">__init__</span><span>(</span><span style="color:rgb(128,0,128)">self</span><span>,</span><span> </span><span>overlayed_scene</span><span>):</span>
<span> </span><span style="color:rgb(0,0,176)">super</span><span>().</span><span style="color:rgb(0,0,255)">__init__</span><span>()</span>
<span> </span><span style="color:rgb(128,0,128)">self</span><span>.</span><span>overlayed_scene</span><span> </span><span>=</span><span> </span><span>overlayed_scene</span>
<span> </span><span style="color:rgb(128,0,128)">def</span><span> </span><span style="color:rgb(0,0,176)">eventFilter</span><span>(</span><span style="color:rgb(128,0,128)">self</span><span>,</span><span> </span><span>watched</span><span>,</span><span> </span><span>event</span><span>):</span>
<span> </span><span style="color:rgb(128,0,128)">print</span><span>(</span><span>watched</span><span>,</span><span> </span><span style="color:rgb(0,0,255)">type</span><span>(</span><span>event</span><span>))</span>
<span> </span><span style="color:rgb(128,0,128)">if</span><span> </span><span>watched</span><span> </span><span style="color:rgb(128,0,128)">is</span><span> </span><span style="color:rgb(128,0,128)">self</span><span>.</span><span>overlayed_scene</span><span> </span><span style="color:rgb(128,0,128)">and</span><span> </span><span style="color:rgb(0,0,176)">issubclass</span><span>(</span><span style="color:rgb(0,0,255)">type</span><span>(</span><span>event</span><span>),</span><span> </span><span>(</span><span>Qt</span><span>.</span><span>QGraphicsSceneEvent</span><span>,</span><span> </span><span>Qt</span><span>.</span><span>QKeyEvent</span><span>,</span><span> </span><span>Qt</span><span>.</span><span>QFocusEvent</span><span>,</span><span> </span><span>Qt</span><span>.</span><span>QTimerEvent</span><span>))</span><span> </span><span style="color:rgb(128,0,128)">or</span><span> </span><span style="color:rgb(0,0,255)">type</span><span>(</span><span>event</span><span>)</span><span> </span><span style="color:rgb(128,0,128)">is</span><span> </span><span>Qt</span><span>.</span><span>QEvent</span><span> </span><span style="color:rgb(128,0,128)">and</span><span> </span><span>event</span><span>.</span><span style="color:rgb(0,0,255)">type</span><span>()</span><span> </span><span style="color:rgb(128,0,128)">is</span><span> </span><span>Qt</span><span>.</span><span>QEvent</span><span>.</span><span>MetaCall</span><span>:</span>
<span style="color:rgb(0,128,0)"># if hasattr(event, 'screenPos') and issubclass(type(event), Qt.QGraphicsSceneEvent):</span>
<span style="color:rgb(0,128,0)"># event.setScenePos(event.widget().mapFromGlobal(event.screenPos()))</span>
<span> </span><span style="color:rgb(0,128,0)"># Without the above, which would require exposing QGraphicsScene*Event.setScenePos functions,</span>
<span> </span><span style="color:rgb(0,128,0)"># OverlayedGV.overlay_item receives correct mouse events only when OverlayedGV.transform is</span>
<span> </span><span style="color:rgb(0,128,0)"># identity.</span>
<span> </span><span style="color:rgb(128,0,128)">return</span><span> </span><span style="color:rgb(128,0,128)">self</span><span>.</span><span style="color:rgb(0,0,176)">event</span><span>(</span><span>event</span><span>)</span>
<span> </span><span style="color:rgb(128,0,128)">else</span><span>:</span>
<span> </span><span style="color:rgb(128,0,128)">return</span><span> </span><span style="color:rgb(0,0,176)">super</span><span>().</span><span style="color:rgb(0,0,176)">eventFilter</span><span>(</span><span>watched</span><span>,</span><span> </span><span>event</span><span>)</span>
<span style="color:rgb(128,0,128)">class</span><span> </span><span style="color:rgb(0,0,176)">OverlayedGV</span><span>(</span><span>Qt</span><span>.</span><span>QGraphicsView</span><span>):</span>
<span> </span><span style="color:rgb(128,0,128)">def</span><span> </span><span style="color:rgb(0,0,255)">__init__</span><span>(</span><span style="color:rgb(128,0,128)">self</span><span>,</span><span> </span><span>scene</span><span>,</span><span> </span><span>parent</span><span>=</span><span style="color:rgb(0,0,255)">None</span><span>):</span>
<span> </span><span style="color:rgb(0,0,176)">super</span><span>().</span><span style="color:rgb(0,0,255)">__init__</span><span>(</span><span>scene</span><span>,</span><span> </span><span>parent</span><span>)</span>
<span> </span><span style="color:rgb(128,0,128)">self</span><span>.</span><span style="color:rgb(0,0,176)">setMouseTracking</span><span>(</span><span style="color:rgb(0,0,255)">True</span><span>)</span>
<span> </span><span style="color:rgb(128,0,128)">self</span><span>.</span><span>overlay_scene</span><span> </span><span>=</span><span> </span><span style="color:rgb(0,0,176)">OverlayGS</span><span>(</span><span>scene</span><span>)</span>
<span> </span><span style="color:rgb(128,0,128)">self</span><span>.</span><span>overlay_item_widget</span><span> </span><span>=</span><span> </span><span>Qt</span><span>.</span><span style="color:rgb(0,0,176)">QTextEdit</span><span>(</span><span style="color:rgb(0,128,128)">'hello world\n'</span><span>*</span><span style="color:rgb(0,78,130)">4</span><span>)</span>
<span> </span><span style="color:rgb(128,0,128)">self</span><span>.</span><span>overlay_item</span><span> </span><span>=</span><span> </span><span style="color:rgb(128,0,128)">self</span><span>.</span><span>overlay_scene</span><span>.</span><span style="color:rgb(0,0,176)">addWidget</span><span>(</span><span style="color:rgb(128,0,128)">self</span><span>.</span><span>overlay_item_widget</span><span>)</span>
<span> </span><span style="color:rgb(128,0,128)">self</span><span>.</span><span>overlay_item</span><span>.</span><span style="color:rgb(0,0,176)">show</span><span>()</span>
<span> </span><span style="color:rgb(128,0,128)">self</span><span>.</span><span>overlay_scene</span><span>.</span><span>changed</span><span>.</span><span style="color:rgb(0,0,176)">connect</span><span>(</span><span style="color:rgb(128,0,128)">self</span><span>.</span><span style="color:rgb(0,0,176)">scene</span><span>().</span><span>invalidate</span><span>)</span>
<span> </span><span style="color:rgb(128,0,128)">def</span><span> </span><span style="color:rgb(0,0,176)">resizeEvent</span><span>(</span><span style="color:rgb(128,0,128)">self</span><span>,</span><span> </span><span>event</span><span>):</span>
<span> </span><span style="color:rgb(0,0,176)">super</span><span>().</span><span style="color:rgb(0,0,176)">resizeEvent</span><span>(</span><span>event</span><span>)</span>
<span> </span><span>size</span><span> </span><span>=</span><span> </span><span style="color:rgb(128,0,128)">self</span><span>.</span><span style="color:rgb(0,0,176)">size</span><span>()</span>
<span> </span><span style="color:rgb(128,0,128)">self</span><span>.</span><span>overlay_scene</span><span>.</span><span style="color:rgb(0,0,176)">setSceneRect</span><span>(</span><span style="color:rgb(0,78,130)">0</span><span>,</span><span> </span><span style="color:rgb(0,78,130)">0</span><span>,</span><span> </span><span>size</span><span>.</span><span style="color:rgb(0,0,176)">width</span><span>(),</span><span> </span><span>size</span><span>.</span><span style="color:rgb(0,0,176)">height</span><span>())</span>
<span> </span><span style="color:rgb(128,0,128)">def</span><span> </span><span style="color:rgb(0,0,176)">drawForeground</span><span>(</span><span style="color:rgb(128,0,128)">self</span><span>,</span><span> </span><span>p</span><span>,</span><span> </span><span>rect</span><span>):</span>
<span> </span><span>p</span><span>.</span><span style="color:rgb(0,0,176)">save</span><span>()</span>
<span> </span><span>p</span><span>.</span><span style="color:rgb(0,0,176)">resetTransform</span><span>()</span>
<span> </span><span style="color:rgb(128,0,128)">try</span><span>:</span>
<span> </span><span style="color:rgb(128,0,128)">self</span><span>.</span><span>overlay_scene</span><span>.</span><span style="color:rgb(0,0,176)">render</span><span>(</span><span>p</span><span>)</span>
<span> </span><span style="color:rgb(128,0,128)">finally</span><span>:</span>
<span> </span><span>p</span><span>.</span><span style="color:rgb(0,0,176)">restore</span><span>()</span>
<span style="color:rgb(128,0,128)">if</span><span> </span><span style="color:rgb(0,0,255)">__name__</span><span> </span><span>==</span><span> </span><span style="color:rgb(0,128,128)">'__main__'</span><span>:</span>
<span> </span><span style="color:rgb(128,0,128)">import</span><span> </span><span style="color:rgb(0,0,255)">sys</span>
<span> </span><span>app</span><span> </span><span>=</span><span> </span><span>Qt</span><span>.</span><span style="color:rgb(0,0,176)">QApplication</span><span>(</span><span style="color:rgb(0,0,255)">sys</span><span>.</span><span style="color:rgb(0,0,255)">argv</span><span>)</span>
<span> </span><span>scene</span><span> </span><span>=</span><span> </span><span>Qt</span><span>.</span><span style="color:rgb(0,0,176)">QGraphicsScene</span><span>()</span>
<span> </span><span>scene</span><span>.</span><span style="color:rgb(0,0,176)">setBackgroundBrush</span><span>(</span><span>Qt</span><span>.</span><span style="color:rgb(0,0,176)">QBrush</span><span>(</span><span>Qt</span><span>.</span><span style="color:rgb(0,0,176)">QColor</span><span>(</span><span>Qt</span><span>.</span><span>Qt</span><span>.</span><span>black</span><span>)))</span>
<span> </span><span>big_box_item</span><span> </span><span>=</span><span> </span><span>scene</span><span>.</span><span style="color:rgb(0,0,176)">addRect</span><span>(</span><span style="color:rgb(0,78,130)">10</span><span>,</span><span> </span><span style="color:rgb(0,78,130)">10</span><span>,</span><span> </span><span style="color:rgb(0,78,130)">300</span><span>,</span><span> </span><span style="color:rgb(0,78,130)">300</span><span>,</span><span> </span><span>Qt</span><span>.</span><span style="color:rgb(0,0,176)">QPen</span><span>(</span><span>Qt</span><span>.</span><span style="color:rgb(0,0,176)">QColor</span><span>(</span><span>Qt</span><span>.</span><span>Qt</span><span>.</span><span>blue</span><span>)),</span><span> </span><span>Qt</span><span>.</span><span style="color:rgb(0,0,176)">QBrush</span><span>(</span><span>Qt</span><span>.</span><span style="color:rgb(0,0,176)">QColor</span><span>(</span><span>Qt</span><span>.</span><span>Qt</span><span>.</span><span>red</span><span>)))</span>
<span> </span><span>overlayed_gv</span><span> </span><span>=</span><span> </span><span style="color:rgb(0,0,176)">OverlayedGV</span><span>(</span><span>scene</span><span>)</span>
<span> </span><span>scene</span><span>.</span><span style="color:rgb(0,0,176)">installEventFilter</span><span>(</span><span>overlayed_gv</span><span>.</span><span>overlay_scene</span><span>)</span>
<span> </span><span>overlayed_gv</span><span>.</span><span style="color:rgb(0,0,176)">show</span><span>()</span>
<span> </span><span>app</span><span>.</span><span style="color:rgb(128,0,128)">exec</span><span>()</span>
</pre></div>
I think it will probably work better to make a QGraphicsView for my overlay scene that renders to an offscreen buffer. I can have that offscreen view filter OverlayedGV's events before they are converted to QGraphicsItem*Events, and I can get really clever and blit the offscreen view's gl framebuffer into that of the OverlayedGV rather than futzing with overlay_scene.render(..). (Although OverlayedGV's viewport is not necessarily a QOpenGLWidget in this example, it is in the application where I'm doing this stuff.)<br><br></div><div>....Anyway! Got a little off track there, but I think setScenePos, setLastScenePos, and perhaps some other similar, supposedly private QGraphicsEvent derivative setters would be quite convenient. It's pretty straightforward to modify and rebuild PyQt5 to have them, but I can't require this of my users, and I've gone to a lot of trouble to make the application pure Python, so including a custom sip module is also no-go.<br></div><div><br></div><div>Thanks,<br></div><div>Erik<br></div></div></div>