[R] tcl/tk return problem

Philippe Grosjean phgrosjean at sciviews.org
Wed Aug 31 16:08:09 CEST 2005


Duncan Murdoch wrote:
> On 8/31/2005 8:57 AM, Prof Brian Ripley wrote:
> 
>> On Wed, 31 Aug 2005, Duncan Murdoch wrote:
>>
>>> Prof Brian Ripley wrote:
>>> > On Wed, 31 Aug 2005, Philippe Grosjean wrote:
>>> >
>>> >
>>> >>deggle wrote:
>>> >>
>>> >>>Hello,
>>> >>>
>>> >>>I'm very new in working with tcl/tk in R and have a problem which 
>>> will
>>> >>>probably
>>> >>>sound silly to most of you.
>>> >>>Here is the code I have problems with:
>>> >>>
>>> >>>readcelfiles <- function()
>>> >>>{
>>> >>>   require(tcltk)
>>> >>>   tt <- tktoplevel()
>>> >>>   tkgrid(tklabel(tt,text="Choose a directory!"))
>>> >>>
>>> >>> OnOK <- function()
>>> >>> {
>>> >>>    fileDir<-tclvalue(tkchooseDirectory())
>>> >>>    data.raw <- ReadAffy(celfile.path=fileDir)
>>> >>>    #return(data.raw)
>>> >>> }
>>> >>>
>>> >>>   OK.but <- tkbutton(tt,text="OK",command=OnOK)
>>> >>>   tkgrid(OK.but)
>>> >>>   tkfocus(tt)
>>> >>>}
>>> >>>
>>> >>>So after clicking on my "OK" button, I choose my directory and 
>>> read the
>>> >>>cel-files.
>>> >>>But now I want to return the object to my workspace ... "return" 
>>> doesn't
>>> >>>work here.
>>> >>
>>> >>I suppose you mean in the User Workspace. Your OnOK function should 
>>> look
>>> >>like that:
>>> >>
>>> >>OnOK <- function() {
>>> >>      fileDir<-tclvalue(tkchooseDirectory())
>>> >>      data.raw <<- ReadAffy(celfile.path=fileDir)
>>> >>}
>>> >>
>>> >>Note that the function overwrites any existing 'data.raw', so this 
>>> could
>>> >>be dangerous. Writting directly in the User Workspace is not advised
>>> >>from inside a function, but here, it is the simplest way to return a
>>> >>result from a tk widget action.
>>> >
>>> >
>>> > Maybe simplest, but not a very good way.  See
>>> > R_SOURCES/src/library/tcltk/R/utils.R for ideas on how to write a 
>>> modal
>>> > dialog box that returns the value selected.
>>> >
>>> > One problem with <<- is that it does not necessarily write in the
>>> > workspace.  You need
>>> >
>>> >    assign("data.raw", ReadAffy(celfile.path=fileDir), 
>>> envir=.GlobalEnv)
>>> >
>>> > to be sure of that.  (The example code I quote does use <<- but in a
>>> > controlled way.)
>>>
>>> This works, and you weren't suggesting it as a good style, but I'd like
>>> to say it's really a bad style to write to .GlobalEnv.
>>
>>
>> It was the question asked! 
> 
> 
> Yes, I agree, but I was pointing out that it is probably the wrong 
> question.
> 
> Duncan Murdoch

This was to provide a direct answer to the question. I think I said it 
is not a good practice. For storing temporary variables for a GUI, I 
prefer to use a dedicated workspace. The very simple functions 
assignTemp(), getTemp() and rmTemp() in the svMisc package (SciViews 
bundle) ease its use. 'TempEnv' is used in SciViews-R, and, after a 
suggestion, John Fox included it also in R Commander (called 'RcmdrEnv' 
there).

May be a modal Tk dialog box is all what is needed here... Although 
since we are speaking about "good and bad questions", I wonder if the 
whole stuff is of any value:

1°) Draw a Tk dialog just with a "Choose a directory!" and an "OK" 
button is totally useless. Why not to display tkchooseDirectory() 
directly? After all, the 'Cancel' button is there in case the user does 
not want to proceed. This error in GUI design is to place in the same 
bag as "Do you want to quit?" -> "Do you really want to quit?" -> "Are 
you really sure you really want to quit?" !!!

2°) However, if the initial idea is to place other info in the Tk 
dialog, it then makes sense. Now, if this is the case, it is not 
necessary to put tkchooseDirectory() in the OnOK() function. The 
following code is doing the job without all the problems mentioned:

 > # This is because I don't have the ReadAffy() function...
 > ReadAffy <- function(celfile.path) return(celfile.path)
 >
 > readcelfiles <- function() {
 >     require(tcltk)
 >     tt <- tktoplevel()
 >     tkgrid(tklabel(tt, text = "Choose a directory!"))
 >     tkgrid(tkbutton(tt, text = "OK",
 >          command = function() tkdestroy(tt)))
 >     tkfocus(tt)
 >     tkwait.window(tt)
 >     fileDir<-tclvalue(tkchooseDirectory())
 >     return(ReadAffy(celfile.path = fileDir))
 > }
 > readcelfiles()

So... perhaps the wrong question is not where one think it is ;-)
Best,

Philippe

>  > If you use a non-modal tcltk dialog you
> 
>> have little choice, as the parent function will have returned and 
>> vanished
>> long ago.  Now, having a widget firing off R commands independently of 
>> the
>> command line is not a great idea (R's evaluator is not multithreaded and
>> this could be interspersed in another computation) so there is a lot 
>> to be
>> said for using dialog boxes modally.
>>
>>> The controlled use of <<- as in tk_select.list from the file you
>>> quoted is really the best way to solve this problem.  As a general
>>> rule, you shouldn't stomp on something you don't own, and functions
>>> don't own variables in .GlobalEnv.
>>
>>
>> One could argue the user who pressed the button does: it is the user
>> workspace.
>>
>>> What tk_select.list does is define OnOK locally, and use <<- to write to
>>> the tk_select.list environment.  Then the result can be manipulated and
>>> returned politely, without stomping on anything anywhere.
>>
>>
> 
> 
>




More information about the R-help mailing list