How to return values ​​from gWidgets and handlers?

I am trying to develop a GUI (using gWidgets) for an R package. My plan was to build a main window containing data, and with buttons invoking small gui wrappers for each function. Unfortunately, I am stuck in the main (?) Problem - I do not know how to transfer data.

any questions:

  • How to send data between separate windows?
  • How to send data from a handler to another window?

My problem is similar: Loading and saving variables in R using gWidgets , but from what I read, using .GlobalEnv is not recommended.

I also saw that someone used the <-operator: http://www.mail-archive.com/r-sig-gui@r-project.org/msg00053.html , but I cannot reproduce it properly ( and this will not work with my example, I think).

The following is a simple example when I try to send text to another window and back if the button is pressed. I tried with returning inside the handler, but this does not work (also not sure if this is allowed). The subtitle immediately returns its value at the end of the function before the handler / inner function can act on the data. I do not know how to contact the handler in the main window.

main <- function(){ library(gWidgets) options(guiToolkit="RGtk2") w <- gwindow(title="Main window", visible=FALSE) txt <- gtext(text="Initial text in main window.", container=w) btn <- gbutton("Send to sub window", container=w) addHandlerChanged(btn, handler = function(h, ...) { shouldbenew <- subwindow(svalue(txt)) svalue(txt) <- paste("The sub window immediately returns 'TRUE', before pushing 'Return to main':", shouldbenew ) } ) visible(w) <- TRUE } subwindow<- function(text){ library(gWidgets) options(guiToolkit="RGtk2") sw <- gwindow(title="Sub window", visible=FALSE) editedtxt <- gtext(text=paste(text, "- Text is transferred to the sub window, but I don't know how to send it back to the main window"), container=sw) btn <- gbutton("Send to main window", container=sw) addHandlerChanged(btn, handler = function(h, ...) { newtxt <- svalue(editedtxt) return(newtxt) } ) visible(sw) <- TRUE } 

Update: Here is the solution I chose as the way forward (as suggested by jverzani), illustrated in the example above. I hope I realized that the proposed solution is correct and that I implemented it in a "beautiful" way, ideally adopted in CRAN.

To summarize, I created a new environment in the main window environment. I edited the helper window to accept the environment in the call. Clicking the button in the subcategory assign edited text to the transferred medium. When the auxiliary window is closed and the main window is in focus, the edited text is accessible from the environment using get .

 main <- function(){ library(gWidgets) options(guiToolkit="RGtk2") # Create a new environment for passing data. .mainGlobal <- new.env() w <- gwindow(title="Main window", visible=FALSE) txt <- gtext(text="Initial text in main window.", container=w) btn <- gbutton("Send to sub window", container=w) addHandlerChanged(btn, handler = function(h, ...) { # Call sub widget passing text and environment. subwindow(text=svalue(txt), env=.mainGlobal) } ) visible(w) <- TRUE addHandlerFocus(w, handler = function (h, ...) { if(exists("myText", envir=.mainGlobal)){ # Retrieve text and update. svalue(txt) <- get("myText", envir=.mainGlobal) } }) } subwindow<- function(text, env=NULL){ library(gWidgets) options(guiToolkit="RGtk2") sw <- gwindow(title="Sub window", visible=FALSE) editedtxt <- gtext(text=text, container=sw) btn <- gbutton("Send to main window", container=sw) addHandlerChanged(btn, handler = function(h, ...) { newtxt <- svalue(editedtxt) assign("myText", newtxt, envir=env) } ) visible(sw) <- TRUE } 
+8
r gwidgets
source share
3 answers

A better approach, but one that requires more processing of your code, is to store GUIs in reference classes.

You call setRefClass with a list of fields (one for each widget) and define the initialization method in which the graphical interface is created. I usually create a function to transfer a call that creates an instance. See setRefClass at the end of a code block.

 mainGui <- suppressWarnings(setRefClass( #Warnings about local assignment not relevant "mainGui", fields = list( #widgets w = "ANY", #"GWindow" txt = "ANY", #"GEdit" btn = "ANY" #"GButton" ), methods = list( initialize = function(windowPosition = c(0, 0)) { "Creates the GUI" w <<- gwindow( "Main window", visible = FALSE, parent = windowPosition ) txt <<- gedit( "Initial text in main window.", container = w ) btn <<- gbutton( "Send to sub window", container = w ) addHandlerChanged( btn, handler = function(h, ...) { subWindow$setText(getText()) } ) visible(w) <- TRUE }, #other methods to access GUI functionality go here getText = function() { svalue(txt) }, setText = function(newTxt) { svalue(txt) <- newTxt } ) )) createMainGui <- function(...) { invisible(mainGui$new(...)) } 
+5
source share

You can simply return widgets for each window in the list. Thus, the main function adds the list(w = w, txt = txt, btn = btn) line list(w = w, txt = txt, btn = btn) to the end to return each widget and make them available after the function finishes.

The following example is the smallest change for your code that works, but in this case, minor flaws in main and subwindow now contain references to return values ​​from each other. The code works, but if you do something more complex, it will be easy to maintain.

 library(gWidgets) options(guiToolkit="tcltk") main <- function(){ w <- gwindow(title="Main window", visible=FALSE) txt <- gtext(text="Initial text in main window.", container=w) btn <- gbutton("Send to sub window", container=w) addHandlerChanged(btn, handler = function(h, ...) { svalue(subWindow$txt) <- svalue(mainWindow$txt) } ) visible(w) <- TRUE list(w = w, txt = txt, btn = btn) } subwindow<- function(text){ sw <- gwindow(title="Sub window", visible=FALSE) editedtxt <- gtext(text="", container=sw) btn <- gbutton("Send to main window", container=sw) addHandlerChanged(btn, handler = function(h, ...) { svalue(mainWindow$txt) <- svalue(subWindow$txt) } ) visible(sw) <- TRUE list(w = sw, txt = editedtxt, btn = btn) } mainWindow <- main() subWindow <- subwindow() 
+1
source share

You can transfer information between gwidgets using independent functions and without knowing the name of the recipient's widget object in advance:

 initMain <- function() { w <- gwindow(title="Main window",visible=FALSE) txt <- gtext(text="Initial text in main window.",container=w) btn <- gbutton("Send to sub window", container=w) list( run = function(partner) { addHandlerChanged(btn, handler = function(h, ...) { svalue(partner$txt) <- svalue(txt) } ) visible(w) <- TRUE }, txt = txt ) } initSubWindow<- function() { w <- gwindow(title="Sub window",visible=FALSE) txt <- gtext(text="huhu",container=w) btn <- gbutton("Send to main window", container=w) list( run = function(partner) { addHandlerChanged(btn, handler = function(h, ...) { svalue(partner$txt) <- svalue(txt) } ) visible(w) <- TRUE }, txt = txt ) } mw <- initMain() sw <- initSubWindow() mw$run(sw) sw$run(mw) 
+1
source share

All Articles