Conversation
bbbe891 to
41ae281
Compare
|
I just tried this out, my goodness, this is amazing @pijyoi ... I had completely written off this functionality some time ago... This works as intended in Chrome, in Safari none of the interactive bits were working, and I got the following error in the console: More errors, I don't think this is an issue with our end of the code, so I'm mostly putting this for record keeping purposes. |
|
I found somewhere and copied it down (but now I can't find the webpage again) that the following will workaround the asyncio error. But the error doesn't seem to prevent the notebook from working, so I just launch it the simple way now. |
Seems like there is some web standard for mouse-wheel : https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent
pyqtgraph, as a Desktop application, doesn't consider the CTRL modifier for mouse wheel, which makes sense for it since |
I think most viz applications prefer to keep modifiers to themselves :) there are other ways though. |
| elif event_type == "wheel": | ||
| pos = QtCore.QPointF(event["x"], event["y"]) | ||
| pixdel = QtCore.QPoint() | ||
| scale = -1.0 # map JavaScript wheel to Qt wheel |
There was a problem hiding this comment.
From what I've seen, Qt uses steps of 120, versus 96 of JS, so using -120/96 == -1.25 here should be more precise.
There was a problem hiding this comment.
I tried out with a mouse wheel. On Qt Desktop, each step generated a delta of 120. But on jupyter_rfb (on Windows Chrome), each step generated a delta of 200 (unscaled). But you are saying that you are getting 96 per step?
There was a problem hiding this comment.
Yes, I get 96 on Windows Firefox. I assumed that this was more or less standard. Arg. I'll do some more research.
There was a problem hiding this comment.
I got 100 on Chrome. I wonder why you get 200. Do you happen to be using a high-rez display?
There was a problem hiding this comment.
Oh yes, I was on a laptop with dpr 2.0.
There was a problem hiding this comment.
I suppose you "feel" the difference in scrolling too. What about using the touchpad, does it feel more sensitive too?
There was a problem hiding this comment.
Oh yes, I was on a laptop with dpr 2.0.
Could you try on Firefox too please? I don't have access to my hidpi screen right now :)
There was a problem hiding this comment.
On the same Windows laptop with dpr 2.0:
Chrome: 200
Firefox: 96
There was a problem hiding this comment.
I made an issue, with a little test html to get some more details: vispy/jupyter_rfb#50
pyqtgraph/jupyter/GraphicsView.py
Outdated
| inverted = False | ||
| evt = QtGui.QWheelEvent(pos, pos, pixdel, angdel, btns, mods, phase, inverted) | ||
| QtCore.QCoreApplication.sendEvent(self.gfxView.viewport(), evt) | ||
| self.request_draw() |
There was a problem hiding this comment.
Typically the event will be emitted into the application, and if the application reacts to it with changes that need a redraw, it will call request_draw. Then again, this should probably work too.
There was a problem hiding this comment.
The implementation done here has jupyter_rfb using pyqtgraph as a library; rather than pyqtgraph using jupyter_rfb as a backend. i.e. pyqtgraph has no idea that it is being used in jupyter_notebook, and would not be able to call request_draw()
I did initially start off with a class inheriting from both pyqtgraph's GraphicsView and RemoteFrameBuffer; but got this error with PySide6: TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
|
Based on @almarklein 's comment on not calling
|
|
Ok, so the downside with not requesting draw on any mouse event is that ViewBox RectMode no longer works since the frame is not redrawn to draw the rubber band. |
|
I don't know the internals of pyqtgraph, but does it no have an update/request_draw method or something that you can tap into? Requesting a new draw on user interaction can be a practical solution, but its not airtight, because there are other events (thinking mostly of timers for animations) that may require a redraw. |
|
As far as I can tell, pyqtgraph internals is Qt. In Desktop Qt, |
So I thought I had a working workaround for the above, but that only handles actions taken by the ViewBox. There are other graphicItems that accept clicks and hover events. (The included ScatterPlot example is one of them) The simplest solution for now is still to request_draw() on each pointer_* event. |
|
Compared to the Desktop Qt version, the ScatterPlot example doesn't show tooltip on hover. There are 2 main items that support clicks, PlotCurveItem and ScatterPlotItem. Clicks don't need special handling, the user, if they hook onto the click signal, could just call request_draw() within their callback. ScatterPlotItem in addition supports hover and the library automatically creates a tooltip on hover, which is already not working in this rfb implementation. If we reduce the scope of what we want to achieve in this implementation, we could remove the request_draw() on pointer_move. |
38a5474 to
67b94e9
Compare
|
Hi @pijyoi This looks good, I did run into one weird behavior, if you run the plotting notebook, and manipulate the linear region item in the 8th plot, the end result isn't quite right. Also super nit-picky, but probably should remove the encoding pragma. |
|
I added the packages that pyqtgraph adds in its CI, but the kernel still crashes upon instantiation of the QApplication. You can try it out here:
I don't see a difference with the Desktop version though. |
I'll capture some video shortly. |
|
okay, to get it to work on binder, I had to set import os
os.environ["QT_QPA_PLATFORM"] = "offscreen" |
|
Okay, the binder link above does work now! |
|
The LinearRegionItem behavior I experienced was only occurring in the Safari web browser (in Chrome everything behaves as it should), which makes me think this potentially a |
|
I think the only thing this PR would need is to add a blurb to the README, and perhaps to the documentation somewhere, but given we don't reference jupyter anywhere in the docs, I'm not sure where the place to put it would be. EDIT: also should we move this bit somewhere else a bit more obfuscated, such as in if "BINDER_SERVICE_HOST" in os.environ:
os.environ["QT_QPA_PLATFORM"] = "offscreen" |
|
Just a reminder, before any merge, I would need to point the binder configuration to fetch from pyqtgraph repo. |
|
Okay, I can replicate the After bumping up the css sizes, running on WSL2 no longer truncates; but it still gets truncated on binder. Although WSL2 was running PySide6 while binder was running PyQt5. |
|
@pijyoi do you want to see if this is a PyQt5 vs. PySide6 difference or you think we should just merge? FWIW this looks good to me. |
|
Okay, ready to merging.
|
|
This LGTM, I would be interested in having a binder config that doesn't depend on conda (so we're not stuck w/ ancient versions of qt bindings); but given this works and a supported environment; let's leave it as is 👍🏻 ...I suppose notebook environments are more likely to use a conda distribution so probably for the best to replicate that environment. |
I did some testing locally with WSL2. It's a Qt5 vs Qt6 difference. |
While I believe you, this really surprised me, and I double-checked the documentation, and sure enough, [Ubuntu 20.04 is the supported configuration](As the provided container is Ubuntu 18.04, we cannot use Qt6.) |

This PR is a continuation of #1963 (comment). Github does not allow attaching
ipynb, so creating a PR seemed the easier way to continue the discussion.A standalone Jupyter Notebook is in this PR that implements a Jupyter PlotWidget and example usage.
What works:
QT_QPA_PLATFORM=offscreenbefore runningjupyter-notebookWhat doesn't work well:
What doesn't work:
Eventually, the PlotWidget class could reside somewhere else within pyqtgraph codebase. But right now, the easiest way to try it out now is to just download the file and run it with your existing installation of pyqtgraph. (plus
jupyter_rfbandpillow)Some notes:
show()-ing the underlyingGraphicsViewwidget causes a window to pop up (on Windows platform anyway). Fortunately, rendering to a QImage works fine without theshow().sendEvent