2

在过去的几个月里,我一直在 RI 中构建一个模拟,希望能够打包。它由两个可用函数和许多内部函数组成,两个可用函数之一在循环时调用这些函数来执行模拟阶段。

一个简单的概念示例是:

# Abstract representation 1st Usable function, generates object containing settings for simulation.
settings <- function(){
  matrix(c(1:4),nrow=2,ncol=2)
}

# Abstract representation of one of many internal functions, does some action in simulation.
int.func <- function(x){
  out <- x*2
  return(out) 
}

# Abstract representation of second usable function, takes settings & invokes internal functions generates results & saves as R object files.
sim.func <- function(x){
  ans <- int.func(x)
  ans2 <- ans-2
  save(ans2, file="outtest")
}

到目前为止,使用我的包,在使用 library() 加载和附加包后使用它:

INPUT <- settings()
fix(settings) # If you want to change from the defaults.
sim.func(INPUT)

没有什么需要从模拟函数返回,因为结果和数据转储被保存为一个带有save()命令的对象,然后可以读取这些对象。

现在我希望它有一个可以与命令行结合使用的简单 GUI——想想 Rcmdr 但更简单,让我从未接触过 R 的同事使用它。gui 需要能够编辑设置 - 就像上面的修复命令一样,将设置对象保存到文件,并从对象文件中读取设置。我用 gWidgets 构建了这个:

gui <- function(){
  INPUT <- matrix(c(1:4),nrow=2,ncol=2)

  mainwin <- gwindow("MainWindow")

  button1 <- gbutton("Edit Settings", cont=mainwin, handler=
                       function(h,...){
                         fix(INPUT)
                         print("Settings Edited")
                       })

  button2 <- gbutton("RUN", cont=mainwin, handler=
                       function(h,...){
                         sim.func(INPUT)
                         print("The run is done")
                       })

  savebutton <- gbutton("Write Settings to File",cont=mainwin, handler=
                          function(h,...){
                            setfilename <- ginput("Please enter the filename")
                            save(INPUT, file=setfilename)
                          })

  loadutton <- gbutton("Load Settings from File", cont=mainwin,
                   handler=function(h,...){
                     fname <- gfile(test="Choose a file", 
                                    type="open", 
                                    action="print",
                                    handler = 
                                      function(h,...){
                                        do.call(h$action, list(h$file))
                                      }
                     )
                     load(fname)})
}

请注意,settings之前函数的工作现在在这个 gui 函数的第一行完成。我将它添加到与上述三个函数相同的 R 文件中,gui作为导出添加到命名空间,将 gWidgets 和 gWidgetstcltk 设置为导入,然后重新构建,然后library()打包并执行gui().

界面出现。但是我有一些问题: gui 显示正常,但是如果我单击 button1(“编辑设置”)通过修复(输入)编辑设置,更改值,关闭编辑器并再次单击按钮以查看更改是否已经持久化并存储在 INPUT 中,但它们没有。读取对象也是如此,它不会覆盖函数 gui() 第一行默认生成的 INPUT 对象。

我认为这与功能环境有关,但我不太确定。在我的包的无 gui 版本中,用户生成包含设置的对象,该对象位于工作区中,并将其作为参数提供给模拟函数。但是,由于使用 gui 版本,所有内容都在函数 gui() 中运行,并且 gWidgets 处理程序使用函数(h,...) 我不禁觉得环境是这里的问题。奇怪的是,当单击按钮 1 时,它会从 gui() 环境中找到 INPUT,但不会在此处进行更改。

有人可以帮忙解决这个问题并建议我需要做什么吗?

很抱歉问了一个很长的问题,但我试图解释清楚。代码是可重现的,这也是问题所在,只需拥有 library(gWidgets, gWidgetstcltk) 并复制和粘贴我在此处提供的代码,以定义函数然后运行gui()​​. 然后单击“编辑设置”按钮,更改单元格,退出,然后再次单击按钮以查看更改是否仍然存在(它们没有)。我提供的抽象示例忠实地再现了我在使用适当的模拟功能时遇到的相同问题,所以如果我不能让它工作,我就不会让真实的东西工作。

谢谢,

本·W。

UEA

塞恩斯伯里实验室。

[编辑] 这是使用 .GlobalEnv 的修复/解决方法:

gui <- function(){
  INPUT <- matrix(c(1:4),nrow=2,ncol=2)
  .GlobalEnv$INPUT <- INPUT
  mainwin <- gwindow("MainWindow")
  button1 <- gbutton("Set", cont=mainwin, handler=
                       function(h,...){
                         INPUT <- .GlobalEnv$INPUT
                         fix(INPUT)
                         print("Settings have been edited...")
                       })
  button2 <- gbutton("RUN", cont=mainwin, handler=
                       function(h,...){
                         sim.func(.GlobalEnv$INPUT)
                         print("The run is done")
                       })
  writebutton <- gbutton("Write Settings to File",cont=mainwin, handler=
                          function(h,...){
                            setfilename <- ginput("Please enter the filename")
                            INPUT <- .GlobalEnv$INPUT
                            save(INPUT, file=setfilename)
                          })

  loadutton <- gbutton("Load Settings from File", cont=mainwin,
                   handler=function(h,...){
                     fname <- gfile(test="Choose a file", 
                                    type="open", 
                                    action="print",
                                    handler = 
                                      function(h,...){
                                        do.call(h$action, list(h$file))
                                      }
                     )
                     load(fname)
                     .GlobalEnv$INPUT <- INPUT})
}
4

0 回答 0