Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

better event docs, better docstring too #654

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 111 additions & 30 deletions 141 docs/source/user_guide/guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,11 @@ Let's take a look at how we can define events to link ``Graphics`` and their pro
Events
------

Events can be a multitude of things: traditional events such as mouse or keyboard events, but they can also be
You can use renderer events, such as mouse or keyboard events, or events related to ``Graphic`` properties.

Events can be a multitude of things: traditional events such as mouse or keyboard events, or events related to ``Graphic`` properties.

There are two ways to add events in ``fastplotlib``.

1) Use the method ::
1) Use the method `add_event_handler()` ::

def event_handler(ev):
pass
Expand All @@ -275,29 +273,16 @@ There are two ways to add events in ``fastplotlib``.


The ``event_handler`` is a user-defined function that accepts an event instance as the first and only positional argument.
Information about the structure of event instances are described below. The `"event_type"`
Information about the structure of event instances are described below. The ``"event_type"``
is a string that identifies the type of event; this can be either a ``pygfx.Event`` or a ``Graphic`` property event.
See the above graphic-specific properties that can be used for events and below for the available ``pygfx`` events.

Rendering engine (``pygfx``) events:
- "key_down"
- "key_up"
- "pointer_down"
- "pointer_move"
- "pointer_up"
- "pointer_enter"
- "pointer_leave"
- "click"
- "double_click"
- "wheel"
- "close"
- "resize"

When an event occurs, the user-defined event handler will receive and event object. Depending on the type of event, the

``graphic.supported_events`` will return a tuple of all ``event_type`` strings that this graphic supports.

When an event occurs, the user-defined event handler will receive an event object. Depending on the type of event, the
event object will have relevant information that can be used in the callback. See below for event tables.

Event Attributes
^^^^^^^^^^^^^^^^
Graphic property events
^^^^^^^^^^^^^^^^^^^^^^^

All ``Graphic`` events have the following attributes:

Expand Down Expand Up @@ -427,13 +412,107 @@ event_type: "selection"
| value | np.ndarray | new [min, max] of selection |
+----------+------------+-----------------------------+

Renderer Events
^^^^^^^^^^^^^^^
Rendering engine events from a Graphic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Rendering engine event handlers can be added to a graphic or to a Figure (see next section).
Here is a description of all rendering engine events and their attributes.

* **pointer_down**: emitted when the user interacts with mouse,
touch or other pointer devices, by pressing it down.

* *x*: horizontal position of the pointer within the widget.
* *y*: vertical position of the pointer within the widget.
* *button*: the button to which this event applies. See "Mouse buttons" section below for details.
* *buttons*: a tuple of buttons being pressed down.
* *modifiers*: a tuple of modifier keys being pressed down. See section below for details.
* *ntouches*: the number of simultaneous pointers being down.
* *touches*: a dict with int keys (pointer id's), and values that are dicts
that contain "x", "y", and "pressure".
* *time_stamp*: a timestamp in seconds.

* **pointer_up**: emitted when the user releases a pointer.
This event has the same keys as the pointer down event.

* **pointer_move**: emitted when the user moves a pointer.
This event has the same keys as the pointer down event.
This event is throttled.

* **double_click**: emitted on a double-click.
This event looks like a pointer event, but without the touches.

* **wheel**: emitted when the mouse-wheel is used (scrolling),
or when scrolling/pinching on the touchpad/touchscreen.

Similar to the JS wheel event, the values of the deltas depend on the
platform and whether the mouse-wheel, trackpad or a touch-gesture is
used. Also, scrolling can be linear or have inertia. As a rule of
thumb, one "wheel action" results in a cumulative ``dy`` of around
100. Positive values of ``dy`` are associated with scrolling down and
zooming out. Positive values of ``dx`` are associated with scrolling
to the right. (A note for Qt users: the sign of the deltas is (usually)
reversed compared to the QWheelEvent.)

On MacOS, using the mouse-wheel while holding shift results in horizontal
scrolling. In applications where the scroll dimension does not matter,
it is therefore recommended to use `delta = event['dy'] or event['dx']`.

* *dx*: the horizontal scroll delta (positive means scroll right).
* *dy*: the vertical scroll delta (positive means scroll down or zoom out).
* *x*: the mouse horizontal position during the scroll.
* *y*: the mouse vertical position during the scroll.
* *buttons*: a tuple of buttons being pressed down.
* *modifiers*: a tuple of modifier keys being pressed down.
* *time_stamp*: a timestamp in seconds.

* **key_down**: emitted when a key is pressed down.

* *key*: the key being pressed as a string. See section below for details.
* *modifiers*: a tuple of modifier keys being pressed down.
* *time_stamp*: a timestamp in seconds.

You can also add events to a ``Figure`` object's renderer. This is useful for defining click events where
you want to map your click position to the nearest graphic object for example.
* **key_up**: emitted when a key is released.
This event has the same keys as the key down event.

Renderer events can be added using either method mentioned above (i.e. using the method or via a decorator).

Time stamps
~~~~~~~~~~~

Since the time origin of ``time_stamp`` values is undefined,
time stamp values only make sense in relation to other time stamps.


Mouse buttons
~~~~~~~~~~~~~

* 0: No button.
* 1: Left button.
* 2: Right button.
* 3: Middle button
* 4-9: etc.


Keys
~~~~

The key names follow the `browser spec <https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent>`_.

* Keys that represent a character are simply denoted as such. For these the case matters:
"a", "A", "z", "Z" "3", "7", "&", " " (space), etc.
* The modifier keys are:
"Shift", "Control", "Alt", "Meta".
* Some example keys that do not represent a character:
"ArrowDown", "ArrowUp", "ArrowLeft", "ArrowRight", "F1", "Backspace", etc.


Add renderer event handlers to a Figure
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

You can add event handlers to a ``Figure`` object's renderer. For example, this is useful for defining click events
where you want to map click positions to the nearest graphic object. See the previous section for a description
of all the renderer events.

Renderer event handlers can be added using a method or a decorator.

For example: ::

Expand Down Expand Up @@ -484,7 +563,9 @@ ImageWidget

Often times, developing UIs for interacting with multi-dimension image data can be tedious and repetitive.
In order to aid with common image and video visualization requirements the ``ImageWidget`` automatically generates sliders
to easily navigate through different dimensions of your data. Let's look at an example: ::
to easily navigate through different dimensions of your data. The image widget supports 2D, 3D and 4D arrays.

Let's look at an example: ::

import fastplotlib as fpl
import imageio.v3 as iio
Expand Down
42 changes: 33 additions & 9 deletions 42 fastplotlib/graphics/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,22 +220,18 @@ def event_handlers(self) -> list[tuple[str, callable, ...]]:

def add_event_handler(self, *args):
"""
Register an event handler.
Register an event handler. Can also be used as a decorator.

Parameters
----------
callback: callable, the first argument
Event handler, must accept a single event argument
*types: list of strings
A list of event types, ex: "click", "data", "colors", "pointer_down"

For the available renderer event types, see
https://jupyter-rfb.readthedocs.io/en/stable/events.html
*types: strings
event types, ex: "click", "data", "colors", "pointer_down"

All feature support events, i.e. ``graphic.features`` will give a set of
all features that are evented

Can also be used as a decorator.
``supported_events`` will return a tuple of all event type strings that this graphic supports.
See the user guide in the documentation for more information on events.

Example
-------
Expand Down Expand Up @@ -316,6 +312,34 @@ def _handle_event(self, callback, event: pygfx.Event):
callback(event)

def remove_event_handler(self, callback, *types):
"""
remove a registered event handler

Parameters
----------
callback: callable
event handler that has been added

*types: strings
event types that were registered with the given callback

Example
-------

.. code-block:: py

# define event handler
def my_handler(event):
print(event)

# add event handler
graphic.add_event_handler(my_handler, "pointer_up", "pointer_down")

# remove event handler
graphic.remove_event_handler(my_handler, "pointer_up", "pointer_down")

"""

# remove from our record first
for t in types:
for wrapper_map in self._event_handler_wrappers[t]:
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.