[R-gui] pure tcl/tk to R-tcltk / labeled frame and image
Dear Peter Dalgaard
Peter Dalgaard wrote:
Thomas Unternaehrer <uth@zhwin.ch> writes:
Dear List, I try to have a picture in a labeled frame like this example shows it: http://incrtcl.sourceforge.net/iwidgets/iwidgets/labeledframe.html At this point I have the following R-code (An example with the R-Logo based on the example by James Wettenhall): ## R ================= library(tcltk) tclRequire("Iwidgets") setwd(paste(system.file(), "/../../doc/html",sep="")) .base <- tktoplevel() tkwm.title(.base, "Labeledframe") tkpack(.base.labelframe <- tkwidget(.base, "iwidgets::labeledframe", labelpos = "nw", labeltext = "Labelframe"), fill = "both", expand = TRUE) .base.labelframe.cs <- .Tk.subwin(.base.labelframe) tclRequire("Img") t.Logo <- tclVar() tkcmd("image", "create", "photo", t.Logo, file = "logo.jpg") tkpack(tklabel(.base.labelframe.cs, image = t.Logo, bg = "white"), fill = "both", expand = TRUE, padx = 5, pady = 5) ##=================== With the following errormessage: Error in structure(.External("dotTclObjv", objv, PACKAGE = "tcltk"), class = "tclObj") : [tcl] bad window path name ".10.1.2". As I understand it right the problem has to do with the fact that "...cs" needs to be a child/sub - window. See the following pure tcl-code: ## Tcl/Tk=============== ## Need to get the childsite so that ## we can properly pack other widgets ## inside set cs [.lf childsite] ##==================== .Tk.subwin seems not to be the right way. I also tried it with .Tcl("pure Tcl commands") and tkcmd but faild. Has anybody an idea how to solve my problem?
The problem is a generic one: If a Tcl extension package generates a widget with internal subwidgets, these are not readily available to the R side of the interface. .Tk.subwin is not going to help because that invents a *new* name.
Ok, this is the same "problem" in all of that Megawidgets, isn't it?
What I presume is going on in your example is that
iwidgets::labeledframe creates a widget called ".10.1" and then
.Tk.subwin() sets up .10.1.2 (Why 2? Did you run it twice?) which
could be OK as an argument to a further widget creation call, but
will not help you get at the subwidgets that have already been created
and named according to the likings of iwidgets::labeledframe. I would
guess that the name you are looking for is ".10.1.cs" (I don't have
Iwidgets to hand on this system).
So what to do about it? You might try passing the the raw ID instead
of the widget, but things like tklabel(".10.1.cs",...) is not going to
work because something will expect it to be an object of class
"tkwin". One fairly obvious idea is to modify .Tk.subwin to take a
name argument, like this:
.Tk.subwin <-
function (parent, name=evalq(num.subwin <- num.subwin + 1, parent$env))
{
ID <- paste(parent$ID, name,
parent$env), sep = ".")
win <- .Tk.newwin(ID)
assign(ID, win, envir = parent$env)
assign("parent", parent, envir = win$env)
win
}
so that .base.labelname.cs <- .Tk.subwin(.base.labelname, "cs") would
work.
If I use your function I get the following error:
....
.Tk.subwin2 <- function (parent, name=evalq(num.subwin <- num.subwin + 1,
parent$env)) {
ID <- paste(c(parent$ID, name, parent$env), sep = ".")
win <- .Tk.newwin(ID)
assign(ID, win, envir = parent$env)
assign("parent", parent, envir = win$env)
win
}
.base.labelframe.cs <- .Tk.subwin2(.base.labelframe, "cs")
tclRequire("Img")
t.Logo <- tclVar()
tcl("image", "create", "photo", t.Logo, file = "logo.jpg")
tkpack(tklabel(.base.labelframe.cs, image = t.Logo, bg = "white"),
fill = "both", expand = TRUE, padx = 5, pady = 5)
Error in structure(.External("dotTclObjv", objv, PACKAGE = "tcltk"),
class = "tclObj") :
[tcl] bad window path name ".1.1.1 cs.1 <environment>".
I've seen that you use the same trick in the tabbed notebook example.
Maybe I have to study that part again.
Thanks a lot Thomas ps: and sorry for my poor english
That's not a problem. However, a couple of programming issues caught my eye: (1) There's really no need to use Tcl style names like .base.labelframe in R. In fact the R interface is designed to enable you to avoid that.
Yes I know, but the name .base.labelframe.image tells me that image (or what ever) is on top of base and labelframe. I find it just usefull.
(2) tkcmd() has been renamed to tcl() (since it was never specific to Tk) and if people would stop piling new issues on top of me, I might actually get around to deprecating the old name.
Ok, last time I used tcl/tk there was just the tkcmd, I think. I have to
read the CHANGES/NEWS-files next time again before posting.
Thanks for that correction.
Just to understand what happend I've tried these two examples
## 1
.base <- tktoplevel()
tkwm.title(.base, "Labelframe")
tkpack(.base.labelframe <- tkwidget(.base, "iwidgets::labeledframe",
labelpos = "nw",
labeltext = "Labelframe"),
fill = "both", expand = TRUE)
cs <- tclVar()
tcl("set", cs, paste("[", .Tk.ID(.base.labelframe), "childsite]"))
t.Logo <- tclVar()
tcl("image", "create", "photo", t.Logo, file = "logo.jpg")
.Tcl(paste("label $cs.l -image ", .Tk.ID(t.Logo)))
[tcl] can't read "cs": no such variable.
This is what you said above I think. The variable "cs" can't be passed
from R to Tcl and back.
## 2
## what I can't understand is that
.Tk.ID(cs) ## is NULL
If I give it an ID by hand it gives me the following:
...
cs$ID <- ".2.1.cs"
.Tcl(paste("label $",.Tk.ID(cs),".l -image ", .Tk.ID(t.Logo), sep = ""))
bad window path name "$.2.1.cs"
That it does not work is not really surprising, but there is maybe more
than just set the path name correctly, isn't it?
Thanks for your help. I'll try to get it work, but if you have a hint
again... would be great.
And thanks for writing that great package.
Thomas