Re: drawing area & events
Peter Groves <[email protected]> Thu, 7 Jan 2010 15:46:24 -0600
| Newsgroups | gmane.comp.lang.ocaml.lib.gtk |
|---|---|
| Message-ID | <[email protected]> |
It's been a while since I dealt with the same issue, so the details are
a little hazy, but here are some things I can glean from my code that
does pretty much what you're looking for:
0) The general technique was to put my drawing_area in something called
a Gbin.event_box, which contains a GObj.event_ops that has it's own
methods to add events and connect to it's event streams. Everything
below is what it looks like in my code:
1) I wasn't able to use the drawing_area directly to get key events,
instead all my code calls a Gobj.event_ops to get key events such as
this code that tries to capture if alt, ctrl or shift are depressed
and returns them as my own "KeyEmitter" which had the API I needed for
my app. The event_ops is associated with an event_box, which in turn
contains my drawing_area. I will show my examples of those in (2) and
(3) below:
##############################################################################
let fromEventOps (gEventOps:GObj.event_ops) = begin
let pressedPipe = Pipe.create () in
let releasedPipe = Pipe.create () in
(** translates for gtk key type to local tKey option. None if
the gtk key is not shift, alt, ctrl *)
gEventOps#add [`KEY_PRESS];
let translateKey = fun gkey -> begin
match gkey with
|ky when (ky = GdkKeysyms._Alt_L) -> Some(Alt)
|ky when (ky = GdkKeysyms._Shift_L) -> Some(Shift)
|ky when (ky = GdkKeysyms._Control_L) -> Some(Ctrl)
|_ -> None
end
in
ignore (gEventOps#connect#key_press ~callback:(fun gEvent ->
begin (*log Debug (lazy("KeyEmitter: gtk key_press callback begin"));*)
let gkey = GdkEvent.Key.keyval gEvent in
begin
match (translateKey gkey) with
|None -> ()
|Some(ky) -> Pipe.handleEvent pressedPipe ky
end;
false
end));
gEventOps#add [`KEY_RELEASE];
ignore (gEventOps#connect#key_release ~callback:(fun gEvent ->
begin (*log Debug (lazy("KeyEmitter: gtk key_release callback
begin"));*) let gkey = GdkEvent.Key.keyval gEvent in
begin
match (translateKey gkey) with
|None -> ()
|Some(ky) -> Pipe.handleEvent releasedPipe ky
end;
false
end));
create ~pressedPipe:pressedPipe ~releasedPipe:releasedPipe
end
*############################################################################
2) My drawing_area is in an event_box. Here is my code where that is
created and calls the code in (1). I'm not sure what everything does,
but it's is in there b/c it was needed to get things to work:
######################################
(** binds a key emitter to a Gtk Event Box *)
let makeKeyEmitter (eventBox:GBin.event_box) mouseEmitter = begin
(** needed so the event box receives key events, not just the
toplevel window*)
eventBox#misc#set_can_focus true;
let enterMon = fun () -> begin
eventBox#misc#grab_focus ()
end
in
Pipe.register (MouseEmitter.enteredFlare mouseEmitter) enterMon;
KeyEmitter.fromEventOps (eventBox#event)
end
#####################################
3) Finally, to call the code in (2) you need an Gbin.event_box, which I
produced as below. Note that the 'childWidget' below ends up being a
drawing_area:
####################################
let create ~childPane = begin
let childWidget = FPane.toGWidget childPane in
let eventBox = GBin.event_box () in
eventBox#add childWidget;
<SNIP>
#####################################
I hope that gets you on the right track and I'm sorry it's not a self
contained example... it's just the code I have lying around. Let me
know if you want any more explanation.
Peter
On Thu, 07 Jan 2010 21:59:07 +0100
Basile STARYNKEVITCH <[email protected]> wrote:
> Hello All,
>
> I am fluent in Ocaml, but new to LablGtk (and still scared of OCaml
> object system).
>
> As an exercise, I want to make a drawing area which captures every
> mouse click and make a polygon of them, until any key is pressed on
> the keyboard. So I coded the following example.
>
> #####################################
>
> (***
> file testdrawar.ml to compile with:
> /usr/bin/ocamlopt -I +lablgtk2 -g -annot lablgtk.cmxa
> gtkInit.cmx testdrawar.ml -o testdrawar ***)
>
> let pointslist = ref ([20,60; 20,40; 40,70] : (int * int) list);;
>
> let drawfun (drawar : GMisc.drawing_area) =
> Printf.eprintf "drawfun %d points\n%!" (List.length !pointslist);
> let drawindow =
> let dmisc = drawar#misc in dmisc#window
> in
> let drawing =
> new GDraw.drawable drawindow
> in
> drawing#polygon ~filled:false !pointslist;
> ()
> ;;
>
> let buttonfun bev =
> let butnum = GdkEvent.Button.button bev
> and x = (int_of_float (GdkEvent.Button.x bev))
> and y = (int_of_float (GdkEvent.Button.x bev))
> in
> Printf.eprintf "buttonfun butnum=%d x=%d y=%d\n%!" butnum x y;
> pointslist := (x,y)::!pointslist;
> ()
> ;;
>
> let keyfun kev =
> let strk = GdkEvent.Key.string kev in
> Printf.eprintf "keyfun %S\n%!" strk;
> pointslist := []
> ;;
>
>
> let topwin = GWindow.window ~title: "testdrawar" ~width: 400 ~height:
> 300 () in let drawar = GMisc.drawing_area ~packing: topwin#add () in
> ignore (drawar#event#add [ `BUTTON_PRESS; `KEY_PRESS]);
> ignore (drawar#event#connect#button_press
> ~callback: (fun bev -> buttonfun bev; drawfun drawar;
> true)); ignore (drawar#event#connect#key_press
> ~callback: (fun kev -> keyfun kev; drawfun drawar;
> true)); ignore (drawar#event#connect#expose ~callback: (fun ev ->
> drawfun drawar; true)); let dmisc = drawar#misc in dmisc#realize ();
> topwin#show ()
> ;;
>
> GMain.Main.main ();;
>
> (*eof*)
>
> #############################################
>
> unfortunately, the code above is incorrect:
>
> For some reason, keyboard events are not caught properly. Should I
> ask for focus?
>
> For some reason, the mouse click coordinates are not correct in the
> drawing area. I should make some conversion (how to do that)?
>
> Any help is appreciated. For the mightly LablGtk contributors, feel
> free to add a similar example to the documentation. It would help a
> lot.
>
> Happy New Year 2010 (and Merry Christmas to those celebrating it
> today, e.g. in Russia).
>
> Regards.
>
> --
> Basile STARYNKEVITCH http://starynkevitch.net/Basile/
> email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
> 8, rue de la Faiencerie, 92340 Bourg La Reine, France
> *** opinions {are only mines, sont seulement les miennes} ***
>
> _______________________________________________
> Lablgtk mailing list
> [email protected]
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/lablgtk