3

I am using the gWidgets toolkit to create a GUI in an R script that is run using Rscript.

When the GUI is created, the script exits.

I can prevent this with a while(TRUE){Sys.sleep(9999)} loop at the end of the script but that seems hacky.

Is there a better way of telling R to exit only when the GUI is closed, or at least to enter the REPL once the GUI is constructed?

Rob Myers
  • 546
  • 4
  • 11
  • That is essentially the same question as this: http://stackoverflow.com/questions/7835947/external-graphical-device-for-littler-or-rscript – Dirk Eddelbuettel Oct 23 '11 at 23:03
  • Correct, Dirk, but the answer to that question is a bit unclear. – Dieter Menne Oct 24 '11 at 06:22
  • Yes, I hadn't seen that question but I don't think it helps as I'm already doing one of the things they suggest. There's also this, but again it's a bit hacky - http://stackoverflow.com/questions/7695177/how-to-provide-expression-to-r-from-command-line-but-stop-r-from-immediately-exi – Rob Myers Oct 24 '11 at 08:55

6 Answers6

4

You might be able to adapt gbasicdialog for your needs. This constructor creates a modal container from which you can spawn other windows. Here is an example:

library(gWidgets)
options(guiToolkit="RGtk2")
require(fortunes)                       # just for fun

hold_it <- gbasicdialog(do.buttons=FALSE)
b <- gbutton("click me for a message", cont=hold_it, handler=function(h,...) {
  gmessage(paste(fortune(), collapse="\n"), parent=hold_it)
})
visible(hold_it, TRUE)

The same works for the "tcltk" toolkit. It uses pretty much what Greg suggests can be done.

jverzani
  • 5,600
  • 2
  • 21
  • 17
  • Really useful and fun....littler + gWidgets rocks. Can't wait to read your new book about GUI programming !! – dickoa Nov 06 '11 at 19:17
3

This subject may be closed but as a newbie to gwidgets, I have been confronted with. The solution given by jverzani is obviously a solution. I have chosen another one, not using any supplementary dialog, just because I don't want one, no other reason at all...

In the handler of the gwindow, after disposal I remove the variable from the environment:

handler = function(h,...) {dispose(EDFAnalysis$w); rm(w,envir=EDFAnalysis)}

where EDFAnalysis is the environment of my script... and w is the main gwindow.

Then, at the end of my script I added:

while(exists("w",EDFAnalysis)){Sys.sleep(5)}

of course, smaller value than 5 or greater value can be used. In my case, 5 s is sufficient and not for ever... :-)

ffeschet
  • 31
  • 1
1

A good way to do it, I've found, is to use the gtkMain() function in the RGtk2 library. This simply keeps the main loop running until gtkMainQuit() is called.

ozjimbob
  • 190
  • 1
  • 6
1

The standard way of dealing with this is to request user input to continue. This one-liner will do the trick.

EDIT: readline only works under interactive use, so I've swapped it for scan, which is a little less pretty.

pause_for_input <- function()
{
  message("Press ENTER to continue")
  invisible(scan(n = 0, quiet = TRUE))
}

So you script should look like

#Create you GUI
#Whatever else
pause_for_input()
Richie Cotton
  • 118,240
  • 47
  • 247
  • 360
  • Hmm. Actually, upon reading the documentation for `readline`, I'm not sure if will work with `littler`. Can someone check please? – Richie Cotton Oct 24 '11 at 14:09
1

If you are using the tcltk package instead of gWidgets then you could possibly use the tkwait.window function from tcltk to tell the script to wait until the gui window goes away before continuing the script.

mlt
  • 1,595
  • 2
  • 21
  • 52
Greg Snow
  • 48,497
  • 6
  • 83
  • 110
  • I'm using the Gtk package but that's just due to familiarity. – Rob Myers Oct 24 '11 at 18:18
  • Does Gtk depend on tcltk? if so then the same solution may apply, otherwise look to see if Gtk has a similar function that waits for an event in the gui. – Greg Snow Oct 24 '11 at 19:47
0

For completeness: ozjimbob already gave the answer for a most "clean" way how to do it. The answer of ffeschet did not work with me, neither on Unix nor on Windows.

Hence, in the main "launching" script, you have to at least have these entries:

options("guiToolkit"="RGtk2")
library(RGtk2)
library(gWidgets)
library(gWidgetsRGtk2)
StartMyGUI()
gtkMain()

In the "child" process "StartMyGUI()", your code could e.g. look like this:

StartMyGUI <- function(handler=function(h,...) {
        dispose(h$obj)
    }) {

window <- gwindow("Hello")
group <- ggroup(container = window)
glabel("Hello World!", container=group, expand=TRUE)

# A group to organize the buttons
button.group <- ggroup(container = group)
# Push buttons to right
addSpring(button.group)
gbutton("OK", handler=handler, container=button.group)
gbutton("Cancel", handler = function(h,...) {
            dispose(window)
            gtkMainQuit()
        },
        container=button.group)

return()
} 

It is only when the user hits the "Cancel" button that gtkMainQuit() will be called, which exits the mother process in the main "launching" script.

GrauBernden
  • 113
  • 8