Getting started
Installation
You can install rendercanvas via pip (or most other Python package managers).
Python 3.10 or higher is required. Pypy is supported.
pip install rendercanvas
Multiple backends are supported, including multiple GUI libraries, but none of these are installed by default. See Backends for details.
We recommend also installing GLFW, so that you have a lightweight backend available from the start:
pip install rendercanvas glfw
Creating a canvas
In general, it’s easiest to let rendercanvas select a backend automatically:
from rendercanvas.auto import RenderCanvas, loop
canvas = RenderCanvas()
# ... code to setup the rendering
loop.run() # Enter main-loop
Rendering to the canvas
The above just shows a grey window. We want to render to it by using wgpu or by generating images.
Depending on the tool you’ll use to render to the canvas, you need a different context. The purpose of the context is to present the rendered result to the canvas. There are currently two types of contexts.
Rendering using bitmaps:
context = canvas.get_bitmap_context()
@canvas.request_draw
def animate():
# ... produce an image, represented with e.g. a numpy array
context.set_bitmap(image)
Rendering with wgpu:
context = canvas.get_wgpu_context()
context.configure(device)
@canvas.request_draw
def animate():
texture = context.get_current_texture()
# ... wgpu code
Physical size, logical size, and pixel-ratio
The context has properties for the logical size, physical size, and the pixel-ratio.
The physical size represent the actual number of “harware pixels” of the canvas surface.
The logical size represents the size in “virtual pixels”, which is used to scale elements like text, points, line thickness etc.
The pixel-ratio represents the factor between the physical size and the logical size.
On regular screens, the physical size and logical size are often equal:
+----+----+----+----+
| | | | | Physical pixels
+----+----+----+----+
+----+----+
| | | Logical pixels, pixel-ratio 1.0
+----+----+
On HiDPI / Retina displays, there are many more pixels, but they are much smaller. To prevent things like text to become tiny, the logical pixels are made larger, i.e. pixel-ratio is increased (by the operating system), usually by a factor 2:
+--+--+--+--+
| | | | | Physical pixels
+--+--+--+--+
+-----+-----+
| | | Logical pixels, pixel-ratio 2.0
+-----+-----+
Other operating system may increase the pixel-ratio as a global zoom factor, to increase the size of elements such as text in all applications. This means that the pixel-ratio can indeed be fractional:
+----+----+----+----+
| | | | | Physical pixels
+----+----+----+----+
+-----+-----+
| | | Logical pixels, pixel-ratio ± 1.2
+-----+-----+
Side note: on MacOS, the pixel-ratio is fixed to either 1.0 or 2.0, usually the latter on a Retina display with reasonable resolution settings. (The OS level zooming is implemented by rendering the whole screen to an offscreen buffer with a different size than the physical screen, and then up/down-scaling that to the screen.)
Async
A render canvas can be used in a fully async setting using e.g. Asyncio or Trio, or in an event-drived framework like Qt.
If you like callbacks, loop.call_later() always works. If you like async, use loop.add_task().
If you make use of async functions (co-routines), and want to keep your code portable across
different canvas backends, restrict your use of async features to sleep and Event;
these are the only features currently implemented in our async adapter utility.
We recommend importing these from rendercanvas.utils.asyncs if you want your code to be portable across different event loop backends.
On the other hand, if you know your code always runs on the asyncio loop, you can fully make use of asyncio. Ditto for Trio.
If you use Qt and get nervous from async code, no worries, when running on Qt, asyncio is not even imported. You can regard most async functions
as syntactic sugar for pieces of code chained with call_later. That’s more or less how our async adapter works :)
Freezing apps
In rendercanvas a PyInstaller-hook is provided to help simplify the freezing process. This hook requires
PyInstaller version 4+. Our hook includes glfw when it is available, so code using rendercanvas.auto
should Just Work.
Note that PyInstaller needs rendercanvas to be installed in site-packages for
the hook to work (i.e. it seems not to work with a pip -e . dev install).