Question

I'm trying to write an app using GtkClutter but I can't get the actors to fire signals. Here is a sample

from gi.repository import GtkClutter, Clutter, Gtk, Gdk

GtkClutter.init([])

class MyCanvas(GtkClutter.Embed):
    __gtype_name__ = 'MyCanvas'

    def __init__(self):
        super(MyCanvas, self).__init__()

        self.stage = self.get_stage()

        self.rect = MyRect()
        self.stage.connect('key-press-event', self.key_press) # This Works!
        self.stage.add_actor(self.rect)
        self.rect.set_position(10, 10)

        self.show_all()

    def key_press(self, widget, event):
        print widget, event


class MyRect(Clutter.Rectangle):
    __gtype_name__ = 'MyRect'

    def __init__(self):
        super(MyRect, self).__init__()
        self.set_color(Clutter.Color.new(255, 255, 255, 0))
        self.set_border_color(Clutter.Color.new(255, 255, 255, 255))
        self.set_border_width(1)
        self.set_size(200, 200)

        self.set_reactive(True)

    # None of the following callbacks work
    # Not even if I explicitly connect signals like 
    # self.connect('button-press-event', self.on_button_press)

    def do_button_press_event(self, event):
        print event

    def do_motion_event(self, event):
        print event


class MyWindow(Gtk.Window):
    __gtype_name__ = 'MyWindow'

    def __init__(self):
        super(MyWindow, self).__init__()
        self.canvas = AnnotateCanvas()
        self.set_events(Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON1_MOTION_MASK)
        self.set_size_request(500, 500)

        vbox_main = Gtk.VBox()
        scrolledwin = Gtk.ScrolledWindow()
        scrolledwin.add_with_viewport(self.canvas)
        vbox_main.pack_end(scrolledwin, True, True, 0)
        self.add(vbox_main)

    def run(self):
        self.show_all()
        self.loop = GObject.MainLoop()
        self.loop.run()


app = MyWindow()
app.run()

All signals are working fine but mouse signals like 'button-press' and 'motion' are not firing on the clutter actor (MyRect/MyCanvas.stage) object. Not even if I give up sub-classing and do everything with stock classes.

I suppose GtkWindow or GtkEmbed is not allowing mouse events to propagate to ClutterStage

Simplified Version

from gi.repository import GObject, GtkClutter, Clutter, Gtk

GtkClutter.init([])

def pressed(widget, event):
    print widget, event

w = Gtk.Window()
e = GtkClutter.Embed.new()
e.set_size_request(500, 500)
w.add(e)

s = e.get_stage()
s.set_color(Clutter.Color.new(0,0,0,0))
s.set_size(500, 500)

r = Clutter.Rectangle()
r.set_color(Clutter.Color.new(255,255,255,255))
r.set_size(200,200)
r.set_position(0,0)
r.set_reactive(True)
s.add_actor(r)

s.connect('button-press-event', pressed)
# r.connect('button-press-event', pressed)
w.show_all()
GObject.MainLoop().run()

Stage and actors fire mouse signals when using just Clutter. It just doesn't work when embedding the stage into a GtkWindow using GtkClutter.Embed

Update

When I try to run the example from http://www.openismus.com/documents/clutter_tutorial/0.9/docs/tutorial/html/sec-stage-widget.html which is in C, it works perfectly well but translating it to python ( https://gist.github.com/1759658 ) doesn't work at all.

By not working, I mean stage does not fire "button-press-event"

Was it helpful?

Solution

I think it has something to do with the fact that GtkClutter.init() must be called before Gtk.init() and Clutter.init(), but the latter two are called upon import of the Gtk and Clutter packages.

Importing the packages like this seems to make your example work:

from gi.repository import GtkClutter
GtkClutter.init([])
from gi.repository import Clutter, GObject, Gtk
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top