From 33521343d68f3fbc03f74134b4862ad99a19c393 Mon Sep 17 00:00:00 2001 From: Almar Klein Date: Wed, 22 Jul 2026 19:09:42 +0200 Subject: [PATCH 1/3] Tweak events.py example to show events in canvas --- examples/events.py | 79 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 4 deletions(-) diff --git a/examples/events.py b/examples/events.py index 76024862..80cfbd84 100644 --- a/examples/events.py +++ b/examples/events.py @@ -2,19 +2,90 @@ Events ------ -A simple example to demonstrate events. Events are printed to the console. +A simple example to demonstrate events. Events are printed in the canvas. """ +import json + from rendercanvas.auto import RenderCanvas, loop +from PIL import Image, ImageDraw, ImageFont +import numpy as np +# import aggdraw + +canvas = RenderCanvas(title="RenderCanvas events on $backend") -canvas = RenderCanvas(title="RenderCanvas events") +events_list = [] +event_count = 0 @canvas.add_event_handler("*") def process_event(event): - if event["event_type"] not in ["pointer_move", "before_draw", "draw"]: - print(event) + global event_count + if event["event_type"] not in ["before_draw"]: + event_count += 1 + events_list.insert(0, event) + events_list[32:] = [] + canvas.request_draw() + + +ctx = canvas.get_bitmap_context() + + +@canvas.request_draw +def draw(): + w, h = ctx.physical_size + ratio = ctx.pixel_ratio + + img = Image.new("RGBA", (w, h), "#abc") + # draw = aggdraw.Draw(img) # like ImageDraw.Draw(img), but with subpixel support + draw = ImageDraw.Draw(img) + + font = ImageFont.load_default(size=16 * ratio) + + x = 10.0 * ratio + y = 0.0 + + draw.text((x, y), text=f"{event_count} events", fill=(0, 0, 0), font=font) + y += 10 * ratio + + a = 1 + for event in events_list: + y += 20 * ratio + if y > h: + break + a = max(0, a - 0.04) + fill = round(160 * (1 - a)), round(170 * (1 - a)), round(180 * (1 - a)) + draw.text( + (x, y), + text=event_to_string(event), + fill=fill, + font=font, + ) + + ctx.set_bitmap(np.asarray(img)) + + +float_keys = ["x", "y", "dx", "dy", "timestamp"] + + +def event_to_string(event): + s = "{ " + for key, value in event.items(): + v = json.dumps(value) + if key in float_keys: + try: + i = v.index(".") + except ValueError: + v += ".0" + else: + v = v[: i + 2] + pad = 6 - len(v) + if pad > 0: + v = " " * pad + v + s += f"{key}: {v}, " + s += " }" + return s if __name__ == "__main__": From d0f88ac909886874814a4982babda3e4b1246407 Mon Sep 17 00:00:00 2001 From: Almar Klein Date: Wed, 22 Jul 2026 19:13:00 +0200 Subject: [PATCH 2/3] Also print --- examples/events.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/events.py b/examples/events.py index 80cfbd84..d3950377 100644 --- a/examples/events.py +++ b/examples/events.py @@ -2,7 +2,7 @@ Events ------ -A simple example to demonstrate events. Events are printed in the canvas. +A simple example to demonstrate events. Events are printed to stdout and shown in the canvas. """ import json @@ -24,7 +24,9 @@ def process_event(event): global event_count if event["event_type"] not in ["before_draw"]: event_count += 1 - events_list.insert(0, event) + event_str = event_to_string(event) + print(event_str) + events_list.insert(0, event_str) events_list[32:] = [] canvas.request_draw() @@ -50,7 +52,7 @@ def draw(): y += 10 * ratio a = 1 - for event in events_list: + for event_str in events_list: y += 20 * ratio if y > h: break @@ -58,7 +60,7 @@ def draw(): fill = round(160 * (1 - a)), round(170 * (1 - a)), round(180 * (1 - a)) draw.text( (x, y), - text=event_to_string(event), + text=event_str, fill=fill, font=font, ) From 5ef37a2a9cc9e363bac37be5eb0914d2e3ab08f7 Mon Sep 17 00:00:00 2001 From: Almar Klein Date: Wed, 19 Aug 2026 11:46:21 +0200 Subject: [PATCH 3/3] refactor a bit for clarity --- README.md | 4 +++- examples/events.py | 45 ++++++++++++++++++++++++++++----------------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 2b5ac1bf..844d6477 100644 --- a/README.md +++ b/README.md @@ -77,12 +77,14 @@ from rendercanvas.auto import RenderCanvas, loop canvas = RenderCanvas(update_mode="continuous") context = canvas.get_bitmap_context() + @canvas.request_draw def animate(): w, h = canvas.get_logical_size() bitmap = np.random.uniform(0, 255, (h, w)).astype(np.uint8) context.set_bitmap(bitmap) + loop.run() ``` @@ -106,8 +108,8 @@ Embed in a Qt application: from PySide6 import QtWidgets from rendercanvas.qt import QRenderWidget -class Main(QtWidgets.QWidget): +class Main(QtWidgets.QWidget): def __init__(self): super().__init__() diff --git a/examples/events.py b/examples/events.py index d3950377..27d6a9e3 100644 --- a/examples/events.py +++ b/examples/events.py @@ -2,7 +2,7 @@ Events ------ -A simple example to demonstrate events. Events are printed to stdout and shown in the canvas. +An example that display events. Events are printed to stdout and shown in the canvas. """ import json @@ -10,28 +10,39 @@ from rendercanvas.auto import RenderCanvas, loop from PIL import Image, ImageDraw, ImageFont import numpy as np -# import aggdraw canvas = RenderCanvas(title="RenderCanvas events on $backend") +ctx = canvas.get_bitmap_context() events_list = [] event_count = 0 +# Create an event handler that gets all events ('*') + + @canvas.add_event_handler("*") def process_event(event): global event_count - if event["event_type"] not in ["before_draw"]: - event_count += 1 - event_str = event_to_string(event) - print(event_str) - events_list.insert(0, event_str) - events_list[32:] = [] - canvas.request_draw() + # Skip specific events + if event["event_type"] in ["before_draw"]: + return -ctx = canvas.get_bitmap_context() + # Just print the dict + print(event) + + # Add to list for drawing in the canvas + event_count += 1 + events_list.append(event_to_string(event)) + events_list[:-32] = [] # limit to 32 entries + + # Invoke a draw + canvas.request_draw() + + +# Draw the events in the canvas itself. A bit complex because of text padding etc. @canvas.request_draw @@ -40,10 +51,11 @@ def draw(): ratio = ctx.pixel_ratio img = Image.new("RGBA", (w, h), "#abc") - # draw = aggdraw.Draw(img) # like ImageDraw.Draw(img), but with subpixel support draw = ImageDraw.Draw(img) - font = ImageFont.load_default(size=16 * ratio) + font_size = 16 + line_height = font_size * 1.25 + font = ImageFont.load_default(size=font_size * ratio) x = 10.0 * ratio y = 0.0 @@ -52,8 +64,8 @@ def draw(): y += 10 * ratio a = 1 - for event_str in events_list: - y += 20 * ratio + for event_str in reversed(events_list): + y += line_height * ratio if y > h: break a = max(0, a - 0.04) @@ -68,10 +80,9 @@ def draw(): ctx.set_bitmap(np.asarray(img)) -float_keys = ["x", "y", "dx", "dy", "timestamp"] - - def event_to_string(event): + """Function to turn an event dict into a string, with consistent space for float values.""" + float_keys = ["x", "y", "dx", "dy", "timestamp"] s = "{ " for key, value in event.items(): v = json.dumps(value)