在"如何将上下文菜单添加到`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)
})
似乎没有通过正确的CCD_ 3值。它总是3
。因此,无论访问哪个上下文菜单,都只能执行h_ctab_clear(field.nr=3)
。
如果gframe
工具提示都是正确的,我很困惑。但不是与每个上下文菜单关联的处理程序。
我怀疑h_ctab_clear(field.nr=i)
有一些范围或类似的问题,但我不确定出了什么问题?
我猜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)
))
)