[R] tkbind (callback)

Fowler, Mark Mark.Fowler at dfo-mpo.gc.ca
Wed Jun 4 20:24:28 CEST 2014


And the path may vary a bit between installations within Windows, but
'somewhere in the R folder' is close enough to find it.

-----Original Message-----
From: Prof Brian Ripley [mailto:ripley at stats.ox.ac.uk] 
Sent: June 4, 2014 2:53 PM
To: Greg Snow; Fowler, Mark
Cc: R help
Subject: Re: [R] tkbind (callback)

On 04/06/2014 18:30, Greg Snow wrote:
> Installed with R is the documentation for tcl/tk (the original 
> language), on my computer it is in the Doc folder/dir of the TCL 
> folder/dir under the R folder.  In that documentation on listbox, near

That will only be the case on Windows.  On other OSes you need to invoke
one of

man listbox
man Tk::Listbox

or perhaps something similar.



> the bottom in the "Default Bindings" section it mentions the virtual 
> event "<<ListboxSelect>>", so I tried that and it worked.  It looks 
> like the double angle brackets are because it is a virtual event 
> rather than a regular (real, non-virtual, ...?) event.  Virtual events

> are not tied to a direct interaction like keypress or mouse click, but

> rather a given widget can generate a virtual event at a time when it 
> makes sense to do so, e.g. <<ListboxSelect>>.
>
> On Wed, Jun 4, 2014 at 10:42 AM, Fowler, Mark
<Mark.Fowler at dfo-mpo.gc.ca> wrote:
>> Thanks for responding, Greg. That works. Plus I wasn't aware of a
ListboxSelect option, which is much more convenient. Trivial question if
you know off the top of your head - why  <<ListboxSelect>> rather than <
ListboxSelect>? I never saw any examples of that type of enclosure.
>>
>> I cced the list. Ran into a lot of dead end threads related to my
question, and callbacks in general, using tcltk or tcltk2. Might spare
others some headaches.
>>
>>
>>
>> -----Original Message-----
>> From: Greg Snow [mailto:538280 at gmail.com]
>> Sent: June 3, 2014 1:41 PM
>> To: Fowler, Mark
>> Cc: R help
>> Subject: Re: [R] tkbind (callback)
>>
>> I think the problem is that the tkbind function is expecting the 3rd
argument to be a function and the arguments of functions passed to
tkbind need to have specific names.  In your call when you do the
binding the OtoFanCallback function is called at that time (hence the
initial print) and its return value (which is the return value of the
final cat call) is used as the binding function, which ends up doing
nothing as you see.
>>
>> I changed your bind command to:
>>
>> tkbind(detlist,"<<ListboxSelect>>", OtofanCallback)
>>
>> and I changed the OtofanCallback function to have no arguments and
ran the script and everything looks much more like it is working, at
least when I changed the selection in the list box I saw the new value
'cat'ed to the screen.
>>
>> hope this helps
>>
>>
>> On Tue, Jun 3, 2014 at 6:32 AM, Fowler, Mark
<Mark.Fowler at dfo-mpo.gc.ca> wrote:
>>> Hello,
>>>
>>>
>>>
>>> I've migrated an ADMB application with a user dialog from S to R. 
>>> The script below will produce a dialog in R, and don't need data to 
>>> address this issue. It works in terms of capturing user inputs to 
>>> pass along, no problem running the ADMB program. However some of the

>>> options have dependencies. E.g. if we fix a parameter it should not 
>>> have an estimation phase, but we want the full suite of phases 
>>> available to the user when the parameter is active. Thus the 
>>> selection of one listbox is constrained by the selection of another 
>>> listbox. I had callback functionality in S for this, and am now 
>>> trying to implement callbacks in
>>> tcltk2 using tkbind. At the bottom of the dialog function below I 
>>> include an attempt at a callback function. Just for one 
>>> parameter-phase pair and scenario to illustrate. It includes a 
>>> troubleshooting cat to tell if it works. When I run this it 
>>> immediately cats the correct value, although this is premature, as I
haven't interacted with the dialog yet.
>>> More importantly, it subsequently ignores interactions. If I change 
>>> the parameter definition in one listbox, the callback should verify 
>>> that the estimation phase is appropriate in the other listbox and 
>>> change it if not. But beyond running the callback function when the 
>>> dialog is created, it does not appear to be active after that. 
>>> Anybody know what I'm doing wrong?
>>>
>>>
>>>
>>> require(tcltk2)
>>>
>>> OtofanGUI=function() {
>>>
>>> OtofanR=tktoplevel()
>>>
>>> tktitle(OtofanR) <- "Age-Related Data Analysis with OTOFAN"
>>>
>>> tkgrid(tklabel(OtofanR,text="DATA SELECTION & 
>>> DEFINITION"),stick="we")
>>>
>>> tkgrid(tklabel(OtofanR,text="If you already have files of 
>>> ADMB-formatted data, and/or optional PIN, click button(s) to 
>>> retrieve
>>> them"))
>>>
>>> ADMBdata <- tk2button(OtofanR, text = "ADMB Data", width = 10, 
>>> command =
>>> function() tkgetOpenFile())
>>>
>>> ADMBfile <- tk2button(OtofanR, text = "ADMB Pin", width = 10, 
>>> command =
>>> function() tkgetOpenFile())
>>>
>>> tkgrid(ADMBdata)
>>>
>>> tkgrid(ADMBfile)
>>>
>>> tkgrid(tklabel(OtofanR,text=""))
>>>
>>> tkgrid(tklabel(OtofanR,text="If you have a dataframe in R, 
>>> confirm/identify it, and the variables to build the ADMB inputs"))
>>>
>>> CustomFile <- tclVar("AgeData")
>>>
>>> tkgrid(tklabel(OtofanR,text="Dataframe name"),tk2entry(OtofanR, 
>>> textvariable=CustomFile, width=20))
>>>
>>> Ages <- tclVar("AgeYears")
>>>
>>> tkgrid(tklabel(OtofanR,text="Age variable"),tk2entry(OtofanR, 
>>> textvariable=Ages, width=20))
>>>
>>> FishLens <- tclVar("FishLength")
>>>
>>> tkgrid(tklabel(OtofanR,text="Fish Length 
>>> variable"),tk2entry(OtofanR, textvariable=FishLens, width=20))
>>>
>>> OtoWts <- tclVar("NA")
>>>
>>> tkgrid(tklabel(OtofanR,text="Otolith Weight 
>>> variable"),tk2entry(OtofanR, textvariable=OtoWts, width=20))
>>>
>>> OtoLens <- tclVar("NA")
>>>
>>> tkgrid(tklabel(OtofanR,text="Otolith Length 
>>> variable"),tk2entry(OtofanR, textvariable=OtoLens, width=20))
>>>
>>> FishWts <- tclVar("NA")
>>>
>>> tkgrid(tklabel(OtofanR,text="Fish Weight 
>>> variable"),tk2entry(OtofanR, textvariable=FishWts, width=20))
>>>
>>> GroupID <- tclVar("NA")
>>>
>>> tkgrid(tklabel(OtofanR,text="Group ID variable"),tk2entry(OtofanR, 
>>> textvariable=GroupID, width=20))
>>>
>>> YearID <- tclVar("NA")
>>>
>>> tkgrid(tklabel(OtofanR,text="Year ID variable"),tk2entry(OtofanR, 
>>> textvariable=YearID, width=20))
>>>
>>> Sex <- tclVar("NA")
>>>
>>> tkgrid(tklabel(OtofanR,text="Sex variable"),tk2entry(OtofanR, 
>>> textvariable=Sex, width=20))
>>>
>>> LFdata <- tclVar("NA")
>>>
>>> tkgrid(tklabel(OtofanR,text="Separate Length-Frequency Dataframe 
>>> name"),tk2entry(OtofanR, textvariable=LFdata, width=20))
>>>
>>> FreqVar <- tclVar("NA")
>>>
>>> tkgrid(tklabel(OtofanR,text="Frequency variable"),tk2entry(OtofanR, 
>>> textvariable=FreqVar, width=20))
>>>
>>> OSTypes <- c("Random at Length", "Simple Random")
>>>
>>> OSlist=tk2listbox(OtofanR, values=OSTypes, selection=1, selectmode =

>>> "single", height = 2, scroll = "none", autoscroll = "x", enabled =
>>> TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="Otolith Sample Type"),OSlist)
>>>
>>> ASTypes <- c("Random at Length", "Simple Random")
>>>
>>> ASlist=tk2listbox(OtofanR, values=ASTypes, selection=1, selectmode =

>>> "single", height = 2, scroll = "none", autoscroll = "x", enabled =
>>> TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="Age Sample Type"),ASlist)
>>>
>>> AppApply <- tk2button(OtofanR, text = "Apply", width = 7, command =
>>> function()
>>>
OtofanDT(tclvalue(ADMBdata),tclvalue(ADMBFile),tclvalue(ADMBPin),ADMBF="
>>> NA",ADMBP="NA",tclvalue(GS),
>>>
>>>
>>> Regdata="NA",tclvalue(CustomFile),tclvalue(Ages),tclvalue(FishLens),
>>> tc
>>> lv
>>> alue(OtoWts),tclvalue(OtoLens),tclvalue(FishWts),tclvalue(GroupID),t
>>> cl
>>> va
>>> lue(YearID),
>>>
>>>                  tclvalue(Sex),tclvalue(LFdata),tclvalue(FreqVar),
>>>
>>>
>>> tclvalue(tclVar(OSTypes[as.numeric(tkcurselection(OSlist))+1])),tclv
>>> al ue (tclVar(ASTypes[as.numeric(tkcurselection(ASlist))+1])),
>>>
>>>
>>> tclvalue(tclVar(LAAdet[as.numeric(tkcurselection(detlist))+1])),tclv
>>> al ue (tclVar(LPhase[as.numeric(tkcurselection(LPlist))+1])),
>>>
>>>
>>> tclvalue(tclVar(Ldist[as.numeric(tkcurselection(Ldlist))+1])),tclval
>>> ue (t clVar(LAAstdev[as.numeric(tkcurselection(LAASDlist))+1])),
>>>
>>>
>>> tclvalue(tclVar(LSDPhase[as.numeric(tkcurselection(LSDlist))+1])),tc
>>> lv al ue(tclVar(LSDdist[as.numeric(tkcurselection(LSDdlist))+1])),
>>>
>>>
>>>
tclvalue(tclVar(LSDcov[as.numeric(tkcurselection(LSDcovlist))+1])),OAA="
>>> NA",tclvalue(tclVar(OAAdet[as.numeric(tkcurselection(odetlist))+1]))
>>> ,
>>>
>>>
>>> tclvalue(tclVar(OPhase[as.numeric(tkcurselection(OPlist))+1])),tclva
>>> lu e( tclVar(Odist[as.numeric(tkcurselection(Odlist))+1])),
>>>
>>>
>>> tclvalue(tclVar(OAAstdev[as.numeric(tkcurselection(OAASDlist))+1])),
>>> tc lv alue(tclVar(OSDPhase[as.numeric(tkcurselection(OSDlist))+1])),
>>>
>>>
>>>
tclvalue(tclVar(OSDdist[as.numeric(tkcurselection(OSDdlist))+1])),CORR="
>>> NA",tclvalue(tclVar(CORest[as.numeric(tkcurselection(CORRlist))+1]))
>>> ,
>>>
>>>
>>> tclvalue(tclVar(CPhase[as.numeric(tkcurselection(CPlist))+1])),GS2="
>>> NA
>>> ",
>>> tclvalue(tclVar(PAAPhase[as.numeric(tkcurselection(PAAlist))+1]))))
>>>
>>> AppCancel <- tk2button(OtofanR, text = "Cancel", width = 7, command 
>>> =
>>> function() tkdestroy(OtofanR))
>>>
>>> tkgrid(AppApply,sticky="w")
>>>
>>> tkgrid(AppCancel,sticky="w")
>>>
>>> #Length at Age Tab
>>>
>>> tkgrid(tklabel(OtofanR,text="LENGTH AT AGE
>>> FITTING"),sticky="we",column=2,row=1)
>>>
>>> LAAdet <- c("Mean, Estimated", "Constrained BY VBGF, Estimated", 
>>> "Constrained TO VBGF, Fixed")
>>>
>>> detlist=tk2listbox(OtofanR, values=c("Mean, Estimated", "Constrained

>>> BY VBGF, Estimated", "Constrained TO VBGF, Fixed"), selection=1, 
>>> selectmode = "single", height = 3, scroll = "none", autoscroll = 
>>> "x", enabled = TRUE, width=30)
>>>
>>> tkgrid(tklabel(OtofanR,text="Determination Method"),column=2,row=2)
>>>
>>> tkgrid(detlist,column=2,row=3)
>>>
>>> LPhase <- c("0", "1", "2", "3")
>>>
>>> LPlist=tk2listbox(OtofanR, values=c("0", "1", "2", "3"), 
>>> selection=3, selectmode = "single", height = 4, scroll = "none", 
>>> autoscroll = "x", enabled = TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="Activation Phase (0 = Fixed, do not
>>> estimate)"),column=2,row=5)
>>>
>>> tkgrid(LPlist,column=2,row=6)
>>>
>>> Ldist <- c("0", "1", "2", "3")
>>>
>>> Ldlist=tk2listbox(OtofanR, values=c("0", "1", "2", "3"), 
>>> selection=1, selectmode = "single", height = 4, scroll = "none", 
>>> autoscroll = "x", enabled = TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="Estimate Distribution in Phase (0 = 
>>> Fixed, do not estimate)"),column=2,row=8)
>>>
>>> tkgrid(Ldlist,column=2,row=9)
>>>
>>> LAAstdev <- c("Traditional Calculation, Fixed", "Constrained BY 
>>> regression, Estimated", "Constrained TO regression, Fixed")
>>>
>>> LAASDlist=tk2listbox(OtofanR, values=c("Traditional Calculation, 
>>> Fixed", "Constrained BY regression, Estimated", "Constrained TO 
>>> regression, Fixed"), selection=1, selectmode = "single", height = 4,

>>> scroll = "none", autoscroll = "x", enabled = TRUE, width=35)
>>>
>>> tkgrid(tklabel(OtofanR,text="Standard Deviation"),column=2,row=11)
>>>
>>> tkgrid(LAASDlist,column=2,row=12)
>>>
>>> LSDPhase <- c("0", "1", "2", "3")
>>>
>>> LSDlist=tk2listbox(OtofanR, values=c("0", "1", "2", "3"), 
>>> selection=4, selectmode = "single", height = 4, scroll = "none", 
>>> autoscroll = "x", enabled = TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="St Dev Activation Phase (0 = Fixed, do 
>>> not
>>> estimate)"),column=2,row=14)
>>>
>>> tkgrid(LSDlist,column=2,row=15)
>>>
>>> LSDdist <- c("0", "1", "2", "3")
>>>
>>> LSDdlist=tk2listbox(OtofanR, values=c("0", "1", "2", "3"), 
>>> selection=1, selectmode = "single", height = 4, scroll = "none", 
>>> autoscroll = "x", enabled = TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="Estimate St Dev Distribution in Phase 
>>> (0 = do not estimate)"),column=2,row=17)
>>>
>>> tkgrid(LSDdlist,column=2,row=18)
>>>
>>> LSDcov <- c("0", "1", "2", "3")
>>>
>>> LSDcovlist=tk2listbox(OtofanR, values=c("0", "1", "2", "3"), 
>>> selection=1, selectmode = "single", height = 4, scroll = "none", 
>>> autoscroll = "x", enabled = TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="Estimate CV in Phase (0 = Fixed, do not
>>> estimate)"),column=2,row=20)
>>>
>>> tkgrid(LSDcovlist,column=2,row=21)
>>>
>>> #Otolith at Age Tab
>>>
>>> tkgrid(tklabel(OtofanR,text="OTOLITH METRICS AT AGE
>>> FITTING"),sticky="we",column=3,row=1)
>>>
>>> OAAdet <- c("Mean, Estimated", "Constrained BY regression, 
>>> Estimated", "Constrained TO regression, Fixed")
>>>
>>> odetlist=tk2listbox(OtofanR, values=c("Mean, Estimated", 
>>> "Constrained BY regression, Estimated", "Constrained TO regression, 
>>> Fixed"), selection=1, selectmode = "single", height = 3, scroll = 
>>> "none", autoscroll = "x", enabled = TRUE, width=30)
>>>
>>> tkgrid(tklabel(OtofanR,text="Determination Method"),column=3,row=2)
>>>
>>> tkgrid(odetlist,column=3,row=3)
>>>
>>> OPhase <- c("0", "1", "2", "3")
>>>
>>> OPlist=tk2listbox(OtofanR, values=c("0", "1", "2", "3"), 
>>> selection=3, selectmode = "single", height = 4, scroll = "none", 
>>> autoscroll = "x", enabled = TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="Activation Phase (0 = Fixed, do not
>>> estimate)"),column=3,row=5)
>>>
>>> tkgrid(OPlist,column=3,row=6)
>>>
>>> Odist <- c("0", "1", "2", "3")
>>>
>>> Odlist=tk2listbox(OtofanR, values=c("0", "1", "2", "3"), 
>>> selection=1, selectmode = "single", height = 4, scroll = "none", 
>>> autoscroll = "x", enabled = TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="Estimate Distribution in Phase (0 = 
>>> Fixed, do not estimate)"),column=3,row=8)
>>>
>>> tkgrid(Odlist,column=3,row=9)
>>>
>>> OAAstdev <- c("Traditional Calculation, Fixed", "Constrained BY 
>>> regression, Estimated", "Constrained TO regression, Fixed")
>>>
>>> OAASDlist=tk2listbox(OtofanR, values=c("Traditional Calculation, 
>>> Fixed", "Constrained BY regression, Estimated", "Constrained TO 
>>> regression, Fixed"), selection=1, selectmode = "single", height = 4,

>>> scroll = "none", autoscroll = "x", enabled = TRUE, width=35)
>>>
>>> tkgrid(tklabel(OtofanR,text="Standard Deviation"),column=3,row=11)
>>>
>>> tkgrid(OAASDlist,column=3,row=12)
>>>
>>> OSDPhase <- c("0", "1", "2", "3")
>>>
>>> OSDlist=tk2listbox(OtofanR, values=c("0", "1", "2", "3"), 
>>> selection=4, selectmode = "single", height = 4, scroll = "none", 
>>> autoscroll = "x", enabled = TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="St Dev Activation Phase (0 = Fixed, do 
>>> not
>>> estimate)"),column=3,row=14)
>>>
>>> tkgrid(OSDlist,column=3,row=15)
>>>
>>> OSDdist <- c("0", "1", "2", "3")
>>>
>>> OSDdlist=tk2listbox(OtofanR, values=c("0", "1", "2", "3"), 
>>> selection=1, selectmode = "single", height = 4, scroll = "none", 
>>> autoscroll = "x", enabled = TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="Estimate St Dev Distribution in Phase 
>>> (0 = do not estimate)"),column=3,row=17)
>>>
>>> tkgrid(OSDdlist,column=3,row=18)
>>>
>>> #Dependencies Tab
>>>
>>> tkgrid(tklabel(OtofanR,text="DEPENDENCIES"),sticky="we",column=4,row
>>> =1
>>> )
>>>
>>> tkgrid(tklabel(OtofanR,text="Correlations"),sticky="we",column=4,row
>>> =2
>>> )
>>>
>>> CORest <- c("Age-Specific", "Age-Invariant")
>>>
>>> CORRlist=tk2listbox(OtofanR, values=c("Age-Specific", 
>>> "Age-Invariant"), selection=1, selectmode = "single", height = 4, 
>>> scroll = "none", autoscroll = "x", enabled = TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="Method"),column=4,row=3)
>>>
>>> tkgrid(CORRlist,column=4,row=3)
>>>
>>> CPhase <- c("1", "2", "3")
>>>
>>> CPlist=tk2listbox(OtofanR, values=c("1", "2", "3"), selection=3, 
>>> selectmode = "single", height = 4, scroll = "none", autoscroll = 
>>> "x", enabled = TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="Activation Phase"),column=4,row=5)
>>>
>>> tkgrid(CPlist,column=4,row=6)
>>>
>>> PAAPhase <- c("1", "2", "3")
>>>
>>> PAAlist=tk2listbox(OtofanR, values=c("1", "2", "3"), selection=1, 
>>> selectmode = "single", height = 4, scroll = "none", autoscroll = 
>>> "x", enabled = TRUE)
>>>
>>> tkgrid(tklabel(OtofanR,text="Activation Phase to Estimate 
>>> Proportions at
>>> Age"),column=4,row=8)
>>>
>>> tkgrid(PAAlist,column=4,row=9)
>>>
>>> OtofanCallback = function(detlist,LAAdet,LPhase,LPlist) {
>>>
>>>                                  if
>>>
(tclvalue(tclVar(LAAdet[as.numeric(tkcurselection(detlist))+1]))!="3"
>>> &
>>> tclvalue(tclVar(LPhase[as.numeric(tkcurselection(LPlist))+1]))=="0")
>>> tk
>>> se
>>> lection.set(detlist, 2)
>>>
>>> cat(tclvalue(tclVar(LAAdet[as.numeric(tkcurselection(detlist))+1])))
>>>
>>> }
>>>
>>> tkbind(detlist,"<Key>", 
>>> OtofanCallback(detlist,LAAdet,LPhase,LPlist))
>>>
>>> }
>>>
>>> OtofanGUI()
>>>
>>>
>>>
>>> [immediately outputs as below]
>>>
>>> Mean, Estimated<Tcl>
>>>
>>>
>>>
>>> Mark Fowler
>>> Population Ecology Division
>>> Bedford Inst of Oceanography
>>> Dept Fisheries & Oceans
>>> Dartmouth NS Canada
>>> B2Y 4A2
>>> Tel. (902) 426-3529
>>> Fax (902) 426-9710
>>> Email Mark.Fowler at dfo-mpo.gc.ca <mailto:Mark.Fowler at dfo-mpo.gc.ca>
>>>
>>>
>>>
>>>
>>>
>>>
>>>          [[alternative HTML version deleted]]
>>>
>>> ______________________________________________
>>> R-help at r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-help
>>> PLEASE do read the posting guide
>>> http://www.R-project.org/posting-guide.html
>>> and provide commented, minimal, self-contained, reproducible code.
>>
>>
>>
>> --
>> Gregory (Greg) L. Snow Ph.D.
>> 538280 at gmail.com
>
>
>


-- 
Brian D. Ripley,                  ripley at stats.ox.ac.uk
Professor of Applied Statistics,  http://www.stats.ox.ac.uk/~ripley/
University of Oxford,             Tel:  +44 1865 272861 (self)
1 South Parks Road,                     +44 1865 272866 (PA)
Oxford OX1 3TG, UK                Fax:  +44 1865 272595



More information about the R-help mailing list