- text entry fields
- drop down menus
- check buttons
- radio buttons
- file selection browsers
- sliding scales

myvar = tclVar('')Later, when you need to get the information that was put into the Tk variable back into the R environment, you can use the

rmyvar = tclvalue(myvar)Another aspect of GUI programming that is different from regular programs has to do with associating actions with certain GUI elements. An obvious example is a button, which when pressed needs to do something. Widgets like this will have an argument, usually called

require(tcltk) coin.power = function(ntoss=100,nsim=1000,prob=.5){ lower = qbinom(.025,ntoss,.5) upper = qbinom(.975,ntoss,.5) rr = rbinom(nsim,ntoss,prob) sum(rr < lower | rr > upper) / nsim } destroy = function(...)tkdestroy(base) tst = function(...){ nsim = as.numeric(tclvalue(nsim_)) ntoss = as.numeric(tclvalue(ntoss_)) prob = as.numeric(tclvalue(prob_)) res = coin.power(ntoss=as.numeric(ntoss),nsim=as.numeric(nsim),prob=as.numeric(prob)) tkconfigure(ans,text=paste(res)) } base = tktoplevel() tkwm.title(base,'Coin Toss') # create a frame to hold the three entries nfrm = tkframe(base) # create tcl variables to associate with the # entry fields -- to include starting values # replace the '' with the desired value nsim_ = tclVar('') ntoss_ = tclVar('') prob_ = tclVar('') f1 = tkframe(nfrm) tkpack(tklabel(f1,text='Nsim',width=8),side='left') tkpack(tkentry(f1,width=10,textvariable=nsim_),side='left') f2 = tkframe(nfrm) tkpack(tklabel(f2,text='Ntoss',width=8),side='left') tkpack(tkentry(f2,width=10,textvariable=ntoss_),side='left') f3 = tkframe(nfrm) tkpack(tklabel(f3,text='Prob',width=8),side='left') tkpack(tkentry(f3,width=10,textvariable=prob_),side='left') # the widgets were packed in the frames, but the frames have # not yet been packed. Remember that nothing can actually be # displayed unless it's been packed. tkpack(f1,side='top') tkpack(f2,side='top') tkpack(f3,side='top') tkpack(nfrm) # now we can repeat the process for the label to hold the # answer, and the frame containing the buttons ans = tklabel(base,text=' ') tkpack(ans,side='top') bfrm = tkframe(base) tkpack(tkbutton(bfrm,text='Run',command=tst),side='left') tkpack(tkbutton(bfrm,text='Quit',command=destroy),side='right') tkpack(bfrm,side='bottom')When we run the program (for example by using the

base = tktoplevel() tkwm.title(base,'Coin Toss') nfrm = tkframe(base) nsim_ = tclVar('') ntoss_ = tclVar('') prob_ = tclVar('') f1 = tkframe(nfrm) tkpack(tklabel(f1,text='Nsim',width=8),side='left',pady=c(5,10)) tkpack(tkentry(f1,width=10,textvariable=nsim_),side='left',padx=c(0,20),pady=c(5,10)) f2 = tkframe(nfrm) tkpack(tklabel(f2,text='Ntoss',width=8),side='left',pady=c(5,10)) tkpack(tkentry(f2,width=10,textvariable=ntoss_),side='left',padx=c(0,20),pady=c(5,10)) f3 = tkframe(nfrm) tkpack(tklabel(f3,text='Prob',width=8),side='left',pady=c(5,10)) tkpack(tkentry(f3,width=10,textvariable=prob_),side='left',padx=c(0,20),pady=c(5,10)) tkpack(f1,side='top') tkpack(f2,side='top') tkpack(f3,side='top') tkpack(nfrm) ans = tklabel(base,text=' ') tkpack(ans,side='top') bfrm = tkframe(base) tkpack(tkbutton(bfrm,text='Run',command=tst),side='left') tkpack(tkbutton(bfrm,text='Quit',command=destroy),side='right') tkpack(bfrm,side='bottom',pady=c(0,10))Here are side-by-side pictures showing the difference between the two versions:

require(tcltk) types = c('flat','groove','raised','ridge','solid','sunken') base = tktoplevel() tkwm.title(base,'Relief Styles') frms = list() mkframe = function(type){ fr = tkframe(base) tkpack(tklabel(fr,text=type,relief=type),side='left',padx=5) tkpack(tkbutton(fr,text=type,relief=type),side='left',padx=5) tkpack(fr,side='top',pady=10) fr } sapply(types,mkframe)Here's a picture of how it looks:

`size=`, the size of the font in points.-
`weight=`, either`"normal"`or`"bold"` -
`slant=`, either`"roman"`or`ïtalic"` -
`underline=`, either`TRUE`or`FALSE` -
`overstrike=`, either`TRUE`or`FALSE`

require(tcltk) somefonts = c('utopia','freemono','lucidatypewriter','mukti', '{new century schoolbook}','freeserif','times','newspaper','freesans') somecolors = c('red','blue','green','yellow','lightblue','tan', 'darkred','lightgreen','white') txt = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' base = tktoplevel() tkwm.title(base,'Fonts') mkfonts = function(font,color){ thefont = tkfont.create(family=font,size=14) tkpack(tklabel(base,text=paste(font,':',txt), font=thefont,background=color), side='top') } mapply(mkfonts,somefonts,somecolors)Here's how it looks: Note that only the specific widget for which

genplot = function(m1,s1,m2,s2,frac,n=100){ dat = c(rnorm((1-frac)*n,m1,s1),rnorm(frac*n,m2,s2)) plot(density(dat),type='l',main='Density of Mixtures') }Now we can create the interface. We'll make three frames: the first will accept the mean and standard deviation for the first distribution, the second will have the mean and standard deviation for the second distribution, and the third will have the slider to determine the fraction of each distribution to use. Recall that we need to create

require(tcltk) doplot = function(...){ m1 = as.numeric(tclvalue(mean1)) m2 = as.numeric(tclvalue(mean2)) s1 = as.numeric(tclvalue(sd1)) s2 = as.numeric(tclvalue(sd2)) fr = as.numeric(tclvalue(frac)) genplot(m1,s1,m2,s2,fr,n=100) } base = tktoplevel() tkwm.title(base,'Mixtures') mainfrm = tkframe(base) mean1 = tclVar(10) mean2 = tclVar(10) sd1 = tclVar(1) sd2 = tclVar(1) frac = tclVar(.5) m1 = tkframe(mainfrm) tkpack(tklabel(m1,text='Mean1, SD1',width=10),side='left') tkpack(tkentry(m1,width=5,textvariable=mean1),side='left') tkpack(tkentry(m1,width=5,textvariable=sd1),side='left') tkpack(m1,side='top') m2 = tkframe(mainfrm) tkpack(tklabel(m2,text='Mean2, SD2',width=10),side='left') tkpack(tkentry(m2,width=5,textvariable=mean2),side='left') tkpack(tkentry(m2,width=5,textvariable=sd2),side='left') tkpack(m2,side='top') m3 = tkframe(mainfrm) tkpack(tkscale(m3,command=doplot,from=0,to=1,showvalue=TRUE, variable=frac,resolution=.01,orient='horiz')) tkpack(m3,side='top') tkpack(mainfrm)Here's how the interface looks: To produce the same sort of GUI, but with the plot in the same frame as the slider, we can use the

img = tkrplot(mainfrm,doplot)Since the

scalefunc = function(...)tkrreplot(img) s = tkscale(mainfrm,command=scalefunc,from=0,to=1,showvalue=TRUE, variable='frac',resolution=.01,orient='horiz')By packing the

require(tcltk) require(tkrplot) genplot = function(m1,s1,m2,s2,frac,n=100){ dat = c(rnorm((1-frac)*n,m1,s1),rnorm(frac*n,m2,s2)) plot(density(dat),type='l',main='Density of Mixtures') } doplot = function(...){ m1 = as.numeric(tclvalue(mean1)) m2 = as.numeric(tclvalue(mean2)) s1 = as.numeric(tclvalue(sd1)) s2 = as.numeric(tclvalue(sd2)) fr = as.numeric(tclvalue(frac)) genplot(m1,s1,m2,s2,fr,n=100) } base = tktoplevel() tkwm.title(base,'Mixtures') mainfrm = tkframe(base) mean1 = tclVar(10) mean2 = tclVar(10) sd1 = tclVar(1) sd2 = tclVar(1) frac = tclVar(.5) img = tkrplot(mainfrm,doplot) scalefunc = function(...)tkrreplot(img) s = tkscale(mainfrm,command=scalefunc,from=0,to=1,showvalue=TRUE, variable=frac,resolution=.01,orient='horiz') tkpack(img) m1 = tkframe(mainfrm) tkpack(tklabel(m1,text='Mean1, SD1',width=10),side='left') tkpack(tkentry(m1,width=5,textvariable=mean1),side='left') tkpack(tkentry(m1,width=5,textvariable=sd1),side='left') tkpack(m1,side='top') m2 = tkframe(mainfrm) tkpack(tklabel(m2,text='Mean2, SD2',width=10),side='left') tkpack(tkentry(m2,width=5,textvariable=mean2),side='left') tkpack(tkentry(m2,width=5,textvariable=sd2),side='left') tkpack(m2,side='top') tkpack(s) tkpack(mainfrm)

<Return> | <FocusIn> |

<Key-x> | <FocusOut> |

<Alt-x> | <Button-1>, <Button-2>, etc. |

<Control-x> | <ButtonRelease-1>, <ButtonRelease-2>, etc. |

<Destroy> | <Double-Button-1>, <Double-Button-2> , etc. |

require(tcltk) makehist = function(...){ df = get(tclvalue(dfname)) thevar = tclvalue(varname) var = as.numeric(df[[thevar]]) hist(var,main=paste("Histogram of",thevar),xlab=thevar) } showb = function(...){ df = get(tclvalue(dfname)) vars = names(df) frms = list() k = 1 mkframe = function(var){ fr = tkframe(base) tkpack(tklabel(fr,width=15,text=var),side='left') tkpack(tkradiobutton(fr,variable=varname,value=var),side='left') tkpack(fr,side='top') fr } frms = sapply(vars,mkframe) tkpack(tkbutton(base,text='Run',command=makehist),side='top') } base = tktoplevel() tkwm.title(base,'Chooser') dfname = tclVar() varname = tclVar() efrm = tkframe(base) tkpack(tklabel(efrm,text='Dataframe: '),side='left') dfentry = tkentry(efrm,textvariable=dfname,width=20) tkbind(dfentry,'<Return>',showb) tkpack(dfentry,side='left') tkpack(efrm)Here's a picture of the widget in both the "closed" and "open" views:

require(tcltk) summ = function(...){ thestring = capture.output(summary(myobj)) thestring = paste(thestring,collapse='\n') tkdelete(txt,'@0,0','end') tkinsert(txt,'@0,0',thestring) } fileName<-tclvalue(tkgetOpenFile()) myobj = read.csv(fileName) base = tktoplevel() tkwm.title(base,'File Open') yscr <- tkscrollbar(base, command=function(...)tkyview(txt,...)) xscr <- tkscrollbar(base, command=function(...)tkxview(txt,...),orient='horiz') txt <- tktext(base,bg="white",font="courier", yscrollcommand=function(...)tkset(yscr,...), xscrollcommand=function(...)tkset(xscr,...), wrap='none', font=tkfont.create(family='lucidatypewriter',size=14)) tkpack(yscr,side='right',fill='y') tkpack(xscr,side='bottom',fill='x') tkpack(txt,fill='both',expand=1) tkpack(tkbutton(base,command=summ,text='Summary'),side='bottom') thestring = capture.output(print(myobj)) thestring = paste(thestring,collapse='\n') tkinsert(txt,"end",thestring) tkfocus(txt)The first picture shows the file chooser (as displayed on a Linux system); the second picture shows the diabetes data set displayed in a text window, and the third picture shows the result of pressing the summary button.

File translated from T

On 10 Mar 2008, 08:45.