在How to add a context menu to a `gframe`?的背面,我正在尝试使用不同的上下文菜单处理程序创建三个不同的gframe
对象。为避免代码重复,我通过循环执行此操作。
考虑这个最小的例子:
require(gWidgets2)
require(gWidgets2RGtk2)
w <- gwindow()
gg <- gvbox(cont=w)
f_lyt_ctab <- list()
l_lyt_ctab <- list()
h_ctab_clear <- function(field.nr=NULL){
stopifnot(!is.null(field.nr))
print(field.nr)
}
lyt_ctab <- glayout(homogeneous=F, cont=gg, expand=TRUE, fill=T)
field.nms <- c("Row Fields", "Column Fields", "Values")
for(i in 1:3){
lyt_ctab[1,i, expand=TRUE, fill=T] <-
f_lyt_ctab[[i]] <- gframe("", horizontal=FALSE,
container=lyt_ctab, expand=TRUE, fill=T)
##have gframe with custom label (and context menu)
l_lyt_ctab[[i]] <- glabel(field.nms[i])
tooltip(l_lyt_ctab[[i]]) <- paste(
"Right-click on", field.nms[i], "to clear field variables")
print(i)
print(field.nms[i])
add3rdmousePopupMenu(l_lyt_ctab[[i]],
list(a=gaction("Clear field", icon="clear",
handler=function(h, ...){
h_ctab_clear(field.nr=i)
})))
f_lyt_ctab[[i]]$block$setLabelWidget(l_lyt_ctab[[i]]$block) # the voodoo
l_lyt_ctab[[i]]$widget$setSelectable(FALSE) # may not be needed
}
麻烦是由于某种原因
handler=function(h, ...){
h_ctab_clear(field.nr=i)
})
似乎没有传递正确的i
值。它总是3
。因此,无论访问哪个上下文菜单,它都只是执行的h_ctab_clear(field.nr=3)
。
如果由于gframe
工具提示都正确的简单原因,我很难过。但不是与每个上下文菜单相关联的处理程序。
我怀疑h_ctab_clear(field.nr=i)
有一些范围或类似问题,但我不确定是什么问题?
答案 0 :(得分:1)
我猜想add3rdmousePopupMenu
可能正在使用handler
函数并在不同的上下文中对其进行评估。此时,它无法解析i
,因为它是函数体中的自由变量,并且原始机箱环境不再可用。一种可能的解决方案是明确创建一个包含i
值的机箱。为了使这更容易,我们可以创建一个辅助函数。
makehandler <- function(i) {
force(i);
function(h, ...){
h_ctab_clear(field.nr=i)
}
}
此函数将包含i
,然后返回一个可用作处理程序的函数。然后你可以像
add3rdmousePopupMenu(l_lyt_ctab[[i]],
list(a=gaction(
"Clear field",
icon="clear",
handler=makehandler(i)
))
)