[Rd] Building an R GUI using gWidgets and RGtk2

Gabor Grothendieck ggrothendieck at gmail.com
Sat Sep 15 05:06:35 CEST 2007


On 9/14/07, Gabor Grothendieck <ggrothendieck at gmail.com> wrote:
> On 9/14/07, Gerlanc, Daniel <Daniel.Gerlanc at geodecapital.com> wrote:
> > Hello,
> >
> > I'm developing a GUI in R that will be used to monitor financial
> > portfolio performance.  The GUI will be distributed as an R package.  So
> > far, I've decided to use the "cairoDevice", "RGtk2", "gWidgets", and
> > "gWidgetsRGtk2" packages to develop the GUI.  I am trying to decide what
> > would be the best way to structure the GUI would be.
> >
> > I've considered 3 approaches to building the GUI.  The first would be to
> > use S4 classes.  I would create parent "gui" object that would store
> > widgets or containers in slots.  Other more specialized guis for
> > different purposes would extend this parent "gui" object.  The
> > difficulty in this approach is R's use of pass-by-value.  Once the gui
> > object has been created, changing any of the slots of the gui requires
> > returning a new GUI object or saving one off in a higher level
> > environment and editing the slots directly.  Editing the slots directly
> > would completely bypass the S4 method dispatch.
> >
> > Another approach would be more functional.  I would create variables
> > that are global within the package or in their own environment and
> > define the package function closures within this environment.  This
> > could work, but the code could get noisy when calls to have be made to
> > distinguish between local variable assignment within the environment of
> > the functions and assignment within the namespace of the package.
> >
> > The third approach I've been considering is using the R.oo package.  I
> > have never used this package before but it appears to provide similar OO
> > features to Java.  Because it allows references, it would seem to
> > provide the features I'm looking for from both the S4 and functional
> > approaches.
> >
> > Any comments or suggestions on these different approaches would be
> > appreciated.
> >
> > Thank you.
> >
> > Sincerely,
> >
> > Daniel Gerlanc
> A fourth approach would be the proto package.  It provides a thin
> layer over environments making use of the prototype (aka object-based)
> style of programming which is fundamental different relative to
> class-based programming (although it is powerful enough to encompass
> class based programming).  The gsubfn package uses proto objects
> as generalizations of replacement strings that hold state from one replacement
> to the next.  An application that may be closer to yours that uses proto
> is ggplot2 which is a recent grid-based plotting package.  The home page is at
>   http://r-proto.googlecode.com .
> See the paper on prototype programming linked on the home page as well
> as the package vignette.

Just to illustrate this further here is a simple example of gWidgets and
proto.  In this example we create a proto object, p, that corresponds to
an ok/cancel dialogue labelled Hello and that prints Hello when OK is
pressed.  The components of p are go, msg and handler.  msg is
a character string, go is a method and handler is a function (to be
a method it would have to pass the proto object as its first arg).

q is created as a child of p so q gets components via
delegation from p.  q overrides msg which was "Hello" in p but is "Bye"
in q.  q acts the same as p except the label is Bye and q prints Bye when
OK is pressed.  Note that we pass the proto object to the handler via
the action= argument.  Here we used a dot (.) to denote the current
object but you could use this or self or any variable name you prefer.

library(proto)
library(gWidgets)
p <- proto(go = function(.) {
	w = gwindow()
	g = ggroup(container = w)
	g.i = ggroup(horizontal=FALSE, container = g)
	glabel(.$msg, container = g.i, expand = TRUE)
	g.i.b = ggroup(container = g.i)
	addSpring(g.i.b)
	gbutton("ok", handler = with(., handler), action = ., container = g.i.b)
	gbutton("cancel", handler = function(h, ...) dispose(w),
		container = g.i.b)
	},
	msg = "Hello",
	handler = function(h, ...) {
		cat("\n", h$action$msg, "\n")
		dispose(h$obj)
	}
)
p$go()  # press ok and Hello is printed

q <- p$proto(msg = "Bye") # q is child of p overriding msg
q$go()  # press ok and Bye is printed



More information about the R-devel mailing list