如何从gWidgets和处理程序返回值?(How to return values from gWi

2019-08-17 15:54发布

我试图建立一个GUI(使用gWidgets)有关R包。 我的计划是建立一个主窗口中保存数据,并用按钮调用每个函数小贵的包装。 不幸的是,我被困在一个基本问题(?) - 我不知道如何将数据传输。

Questons:

  • 如何单独的窗口之间正确地发送数据?
  • 如何从另一个窗口中处理程序中发送的数据?

我的问题是相似的: 加载并与gWidgets r保存变量 ,但是从我已阅读使用.GlobalEnv不推荐。

我也看到有人使用<< -运营商: http://www.mail-archive.com/r-sig-gui@r-project.org/msg00053.html ,但我不能正确地再现它(和它不会与我的工作,例如,我认为)。

下面是一个简单的例子,当我尝试将文本发送到另一个窗口,然后再返回如果按下了按钮。 我曾尝试与处理器中的回报,但不起作用(也不知道是否是允许的)。 子窗口立即在函数的末尾返回其值,前处理程序/内功能可以对数据起作用。 我不知道如何从处理器到主窗口伸手。

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

}

更新:这里是我挑选作为前进的方向(如由jverzani建议的)的解决方案,使用上面的例子示出。 我希望我明白了建议的解决方案正确,并且我已经在一个“好”的方式,在CRAN接受的理想付诸实施。

总结我的主窗口环境中创造了一个新的环境。 我编辑的子窗口采取呼叫的环境。 在子窗口中按下按钮, assign所编辑的文字传递的环境。 当关闭子窗口,在主窗口进入焦点,编辑的文本是从使用环境访问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

}

Answer 1:

涉及您的代码中更大的返工一个更好的办法,但一个,是图形用户界面存储在引用类。

调用setRefClass与(一个用于每个插件)字段的列表,以及定义在其中创建GUI的方法的initialise。 我通常创建一个函数来包装创建一个实例调用。 见setRefClass在代码块的末尾。

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(...))
}    


Answer 2:

你可以只返回小部件列表中的每个窗口。 因此,主要的功能添加行list(w = w, txt = txt, btn = btn)在结束时返回每个插件,使他们可以访问的功能完成后。

下面的例子是你的代码工作的最小变化,但有一个小缺陷在mainsubwindow现在包含对彼此的返回值的引用。 代码工作,但如果你正在做的事情比较复杂,它可以很容易变得难以维持。

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()


Answer 3:

可以通过使用独立的功能和不预先知道接收器窗口小部件的对象名传递gwidgets之间的信息:

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)


文章来源: How to return values from gWidgets and handlers?
标签: r gwidgets