Skip to content
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

Fix and clean docs #14

Merged
merged 4 commits into from
Nov 11, 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
24 changes: 19 additions & 5 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
rendercanvas base classes
=========================
API
===

.. autoclass:: rendercanvas.base.BaseRenderCanvas
These are the base classes that make up the rendercanvas API:

* The :class:`~rendercanvas.BaseRenderCanvas` represets the main API.
* The :class:`~rendercanvas.BaseLoop` provides functionality to work with the event-loop and timers in a generic way.
* The :class:`~rendercanvas.BaseTimer` is returned by some methods of ``loop``.
* The :class:`~rendercanvas.EventType` specifies the different types of events that can be connected to with :func:`canvas.add_event_handler() <rendercanvas.BaseRenderCanvas.add_event_handler>`.

.. autoclass:: rendercanvas.BaseRenderCanvas
:members:
:member-order: bysource

.. autoclass:: rendercanvas.BaseLoop
:members:
:member-order: bysource

.. autoclass:: rendercanvas.base.BaseLoop
.. autoclass:: rendercanvas.BaseTimer
:members:
:member-order: bysource

.. autoclass:: rendercanvas.base.BaseTimer
.. autoclass:: rendercanvas.EventType
:members:
:member-order: bysource
3 changes: 3 additions & 0 deletions docs/backendapi.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Backend API
===========
TODO
99 changes: 30 additions & 69 deletions docs/gui.rst → docs/backends.rst
Original file line number Diff line number Diff line change
@@ -1,58 +1,23 @@
gui API
=======
Backends
========

.. currentmodule:: rendercanvas

You can use vanilla wgpu for compute tasks and to render offscreen. To
render to a window on screen we need a *canvas*. Since the Python
ecosystem provides many different GUI toolkits, rendercanvas implements a base
canvas class, and has builtin support for a few GUI toolkits. At the
moment these include GLFW, Jupyter, Qt, and wx.


The Canvas base classes
-----------------------

For each supported GUI toolkit there is a module that implements a ``RenderCanvas`` class,
which inherits from :class:`BaseRenderCanvas`, providing a common API.
The GLFW, Qt, and Jupyter backends also inherit from :class:`WgpuAutoGui` to include
support for events (interactivity). In the next sections we demonstrates the different
canvas classes that you can use.


Events
------

To implement interaction with a ``RenderCanvas``, use the :func:`BaseRenderCanvas.add_event_handler()` method.
Events come in the following flavours:

.. autoclass:: EventType
:members:


The auto GUI backend
--------------------
The auto backend
-----------------

Generally the best approach for examples and small applications is to use the
automatically selected GUI backend. This ensures that the code is portable
automatically selected backend. This ensures that the code is portable
across different machines and environments. Using ``rendercanvas.auto`` selects a
suitable backend depending on the environment and more. See
:ref:`interactive_use` for details.

To implement interaction, the ``canvas`` has a :func:`WgpuAutoGui.handle_event()` method
that can be overloaded. Alternatively you can use it's :func:`WgpuAutoGui.add_event_handler()`
method. See the `event spec <https://jupyter-rfb.readthedocs.io/en/stable/events.html>`_
for details about the event objects.


.. code-block:: py

from wgpu.gui.auto import RenderCanvas, run, call_later
from rendercanvas.auto import RenderCanvas, loop

canvas = RenderCanvas(title="Example")
canvas.request_draw(your_draw_function)

run()
loop.run()


Support for GLFW
Expand All @@ -64,31 +29,29 @@ but you can replace ``from rendercanvas.auto`` with ``from rendercanvas.glfw`` t

.. code-block:: py

from wgpu.gui.glfw import RenderCanvas, run, call_later
from rendercanvas.glfw import RenderCanvas, loop

canvas = RenderCanvas(title="Example")
canvas.request_draw(your_draw_function)

run()
loop.run()


Support for Qt
--------------

There is support for PyQt5, PyQt6, PySide2 and PySide6. The rendercanvas library detects what
library you are using by looking what module has been imported.
RenderCanvas has support for PyQt5, PyQt6, PySide2 and PySide6. It detects what
qt library you are using by looking what module has been imported.
For a toplevel widget, the ``rendercanvas.qt.RenderCanvas`` class can be imported. If you want to
embed the canvas as a subwidget, use ``rendercanvas.qt.QRenderWidget`` instead.

Also see the `Qt triangle example <https://github.com/pygfx/wgpu-py/blob/main/examples/triangle_qt.py>`_
and `Qt triangle embed example <https://github.com/pygfx/wgpu-py/blob/main/examples/triangle_qt_embed.py>`_.

.. code-block:: py

# Import any of the Qt libraries before importing the RenderCanvas.
# This way wgpu knows which Qt library to use.
# This way rendercanvas knows which Qt library to use.
from PySide6 import QtWidgets
from wgpu.gui.qt import RenderCanvas
from rendercanvas.qt import RenderCanvas # use this for top-level windows
from rendercanvas.qt import QRenderWidget # use this for widgets in you application

app = QtWidgets.QApplication([])

Expand All @@ -104,17 +67,15 @@ and `Qt triangle embed example <https://github.com/pygfx/wgpu-py/blob/main/examp
Support for wx
--------------

There is support for embedding a wgpu visualization in wxPython.
For a toplevel widget, the ``gui.wx.RenderCanvas`` class can be imported. If you want to
embed the canvas as a subwidget, use ``gui.wx.RenderWidget`` instead.
RenderCanvas has support for wxPython.
For a toplevel widget, the ``rendercanvas.wx.RenderCanvas`` class can be imported. If you want to
embed the canvas as a subwidget, use ``rendercanvas.wx.RenderWidget`` instead.

Also see the `wx triangle example <https://github.com/pygfx/wgpu-py/blob/main/examples/triangle_wx.py>`_
and `wx triangle embed example <https://github.com/pygfx/wgpu-py/blob/main/examples/triangle_wx_embed.py>`_.

.. code-block:: py

import wx
from wgpu.gui.wx import RenderCanvas
from rendercanvas.wx import RenderCanvas

app = wx.App()

Expand All @@ -137,7 +98,7 @@ object, but in some cases it's convenient to do so with a canvas-like API.

.. code-block:: py

from wgpu.gui.offscreen import RenderCanvas
from rendercanvas.offscreen import RenderCanvas

# Instantiate the canvas
canvas = RenderCanvas(size=(500, 400), pixel_ratio=1)
Expand All @@ -154,30 +115,30 @@ object, but in some cases it's convenient to do so with a canvas-like API.
Support for Jupyter lab and notebook
------------------------------------

WGPU can be used in Jupyter lab and the Jupyter notebook. This canvas
RenderCanvas can be used in Jupyter lab and the Jupyter notebook. This canvas
is based on `jupyter_rfb <https://github.com/vispy/jupyter_rfb>`_, an ipywidget
subclass implementing a remote frame-buffer. There are also some `wgpu examples <https://jupyter-rfb.readthedocs.io/en/stable/examples/>`_.

.. code-block:: py

# from wgpu.gui.jupyter import RenderCanvas # Direct approach
from wgpu.gui.auto import RenderCanvas # Approach compatible with desktop usage
# from rendercanvas.jupyter import RenderCanvas # Direct approach
from rendercanvas.auto import RenderCanvas # also works, because rendercanvas detects Jupyter

canvas = RenderCanvas()

# ... wgpu code
# ... rendering code

canvas # Use as cell output


.. _interactive_use:

Using a canvas interactively
----------------------------
Interactive use
---------------

The rendercanvas gui's are designed to support interactive use. Firstly, this is
realized by automatically selecting the appropriate GUI backend. Secondly, the
``run()`` function (which normally enters the event-loop) does nothing in an
The rendercanvas backends are designed to support interactive use. Firstly, this is
realized by automatically selecting the appropriate backend. Secondly, the
``loop.run()`` method (which normally enters the event-loop) does nothing in an
interactive session.

Many interactive environments have some sort of GUI support, allowing the repl
Expand All @@ -191,7 +152,7 @@ honor that and use Qt instead.
On ``jupyter console`` and ``qtconsole``, the kernel is the same as in ``jupyter notebook``,
making it (about) impossible to tell that we cannot actually use
ipywidgets. So it will try to use ``jupyter_rfb``, but cannot render anything.
It's theefore advised to either use ``%gui qt`` or set the ``WGPU_GUI_BACKEND`` env var
It's therefore advised to either use ``%gui qt`` or set the ``WGPU_GUI_BACKEND`` env var
to "glfw". The latter option works well, because these kernels *do* have a
running asyncio event loop!

Expand All @@ -204,7 +165,7 @@ On IPython (the old-school terminal app) it's advised to use ``%gui qt`` (or
On IDE's like Spyder or Pyzo, rendercanvas detects the integrated GUI, running on
glfw if asyncio is enabled or Qt if a qt app is running.

On an interactive session without GUI support, one must call ``run()`` to make
On an interactive session without GUI support, one must call ``loop.run()`` to make
the canvases interactive. This enters the main loop, which prevents entering new
code. Once all canvases are closed, the loop returns. If you make new canvases
afterwards, you can call ``run()`` again. This is similar to ``plt.show()`` in Matplotlib.
Loading