I am migrating some older code from gtk2 to gtk3 and encountering problems in refreshing/rendering/updating. So gtk3 has moved to use draw
instead of the old expose_event
and this has caused the context to be an argument of the function and that bit I have figured out. Now in the GTK3 documentation I found this:
Draw signals are normally delivered when a drawing area first comes onscreen, or when it’s covered by another window and then uncovered. You can also force an expose event by adding to the “damage region” of the drawing area’s window; gtk_widget_queue_draw_area() and gdk_window_invalidate_rect() are equally good ways to do this. You’ll then get a draw signal for the invalid region.
And in my code I do this invalidating like this:
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk as gdk
from gi.repository import Gtk as gtk
from gi.repository import Pango as pango
from gi.repository import GLib as glib
def draw(self, ctx):
"""Draw the canvas."""
# wallpaper
ctx.set_source_rgb(0., 0., 0.)
ctx.rectangle(0, 0, 1, 1)
ctx.fill()
ctx.set_line_width(0.005)
ctx.set_line_join(cairo.LINE_JOIN_ROUND)
txtstart = 0.05
for i in sorted(self.draw_que):
item = self.draw_que[i]
#...
#DRAW WHAT'S IN QUEUE
#...
glib.timeout_add(self.refresh_interval, self.redraw)
def on_draw(self, widget, context):
"""Callback for draw (used to be expose_event)."""
rect = widget.get_allocation()
context.rectangle(0, 0, rect.width, rect.height)
context.clip()
context.scale(rect.width, rect.height)
self.draw(context)
return False
def redraw(self):
"""Callback for the idle_add drawing-loop."""
if self.get_property('window'):
alloc = self.get_allocation()
rect = gdk.Rectangle(0, 0, alloc.width, alloc.height)
self.get_property('window').invalidate_rect(rect, True)
self.get_property('window').process_updates(True)
And for the life of me I cannot figure out why the Drawing Area only updates when I switch between windows. I have set refresh_interval = 50
milliseconds, and if I print the refresh_interval just under the glib.timeout_add
call, I get a few prints each time I switch from my gui window to the terminal and back, otherwise it prints nothing and clearly does not refresh at all unless the window switch has just happened.
In short the draw_queue[i] is drawn each time I switch active windows and then gets "glued" to that value until I switch again, and then it's refreshed about four times (so the redrawing happens for 200ms). And my goal is to have the drawing area be updated constantly (each 50ms).
Any tips on how to fix this?
Using Ubuntu 20.04, python 3.8 and gtk3
This used to work on the gtk2 implementation
Here is a screencap of when I print the time of a draw event emitted:
I print the current time each time on_draw
is called and manually start the program, toggle windows a few times and close the program.:wq
The same in text:
pygame 2.1.2 (SDL 2.0.16, Python 3.8.10)
Hello from the pygame community. https://www.pygame.org/contribute.html
Connecting to: <tobiiresearch.implementation.EyeTracker.EyeTracker object at 0x7ff0d53e5790>
draw event received at 2023-01-25 20:40:20.356367
draw event received at 2023-01-25 20:40:20.370740
draw event received at 2023-01-25 20:40:20.387894
draw event received at 2023-01-25 20:40:20.408587
draw event received at 2023-01-25 20:40:25.214985
draw event received at 2023-01-25 20:40:29.183180
draw event received at 2023-01-25 20:40:29.209396
draw event received at 2023-01-25 20:40:29.236468
draw event received at 2023-01-25 20:40:29.252261
draw event received at 2023-01-25 20:40:29.270075
draw event received at 2023-01-25 20:40:29.287464
draw event received at 2023-01-25 20:40:29.301483
draw event received at 2023-01-25 20:40:29.320029
draw event received at 2023-01-25 20:40:29.336251
draw event received at 2023-01-25 20:40:29.352848
draw event received at 2023-01-25 20:40:29.373359
draw event received at 2023-01-25 20:40:30.231043
draw event received at 2023-01-25 20:40:30.484992
ldrop mainloop stopped.
ldrop instance deleted.