Prompt to put input string to variable - R - r

I am running an R script daily that I would like to prompt me to enter data when selecting all the whole script.
I have already tried readline(prompt = ), which prompts in the rstudio console, but it does not prompt me if I select all code to run. I also did not like the prompt being in the console because it was easy to overlook.
I have also looked into library(tcltk), in hopes that a message box could help, but nothing I tried seemed to work.

Here's a method using library(tcltk)
EntryBox <- function(label = 'Enter', title = 'Entry Box') {
tt <- tktoplevel()
tkwm.title(tt, title)
done <- tclVar(0)
tkbind(tt,"<Destroy>", function() tclvalue(done) <- 2)
result <- tclVar("")
cancel.but <- tkbutton(tt, text='Cancel', command=function() tclvalue(done) <- 2)
submit.but <- tkbutton(tt, text="Submit", command=function() tclvalue(done) <- 1)
tkgrid(tklabel(tt, text=label), tkentry(tt, textvariable=result), pady=3, padx=3)
tkgrid(submit.but, cancel.but, pady=3, padx=3)
tkfocus(tt)
tkwait.variable(done)
if(tclvalue(done) != 1) result <- "" else result <- tclvalue(result)
tkdestroy(tt)
return(result)
}
x <- EntryBox(label = 'Enter a string'); x

Related

Display message and rerun the code using gWidgets in R

x <- gconfirm("Run Program?",title="gConfirm")
if (x){
w <- gwindow(title="List of Programs",visible=TRUE)
g = ggroup(horizontal = FALSE, cont=w)
glabel("Please select the Program", cont=g)
ptype <- c("A","B")
temp <- gcombobox(ptype , cont=g)
addHandlerChanged(temp , handler=function(...){})
gbutton("Run", cont=g,handler = function(...){
print(svalue(temp)
dispose(g)
runagain <- gconfirm("Run again?",title="gConfirm")
if(runagain){
## If user clicks okay, I want to start running again from the third line of the code, w <- gwindow......)**
}
}
Can anyone hint a work around that? Also how do I display the svalue(temp) in to similar UI box instead of printing it on the console. Any help is much appreciated.
SOmething like this might get you what you want:
library(gWidgets2)
programs = list("Program A"="a.R",
"Program B" = "b.R")
w <- gwindow("run programs")
g <- ggroup(cont=w, horizontal=FALSE)
fl <- gformlayout(cont=g)
cb <- gcombobox(names(programs), cont=fl, label="Select a program to run")
b <- gbutton("Run selected program", cont=fl, label="", handler=function(h,...) {
prog <- svalue(cb)
val <- gconfirm(sprintf("Run program %s?", prog), parent=w)
if (val) {
source(programs[[val]])
gmessage("All done", parent=w)
}
})

Read csv using gfilebrowse from gWidgets

I am trying to build a GUI using gWidgets R library to download satellite imagery. The intention is to read the urls from a comma separated values file. The GUI looks ok but it does not do what I expect it to do. I am doing something wrong, any help is greatly appreciated.
Here is the sample data:
Online.Access.URLs <- c("http://e4ftl01.cr.usgs.gov//MODIS_Composites/MOLT/MOD09A1.005/2000.02.18/MOD09A1.A2000049.h09v06.005.2006268183648.hdf",
"http://e4ftl01.cr.usgs.gov//MODIS_Composites/MOLT/MOD09A1.005/2000.02.26/MOD09A1.A2000057.h09v06.005.2006270065224.hdf",
"http://e4ftl01.cr.usgs.gov//MODIS_Composites/MOLT/MOD09A1.005/2000.03.05/MOD09A1.A2000065.h09v06.005.2006269234536.hdf")
Producer.Granule.ID <- c("MOD09A1.A2000049.h09v06.005.2006268183648.hdf",
"MOD09A1.A2000057.h09v06.005.2006270065224.hdf",
"MOD09A1.A2000065.h09v06.005.2006269234536.hdf")
df <- data.frame(Producer.Granule.ID,Online.Access.URLs)
write.csv(df,"C:\\GUI_test\\h09v06v3.csv",row.names=FALSE)
And this is my try:
my.DownloadHDF <- function(){
library(gWidgets)
library(gWidgetstcltk)
library(RCurl)
options(guiToolkit = "tcltk")
win <- gwindow("Download HDF with R!", visible = FALSE)
csv.frame <- gframe("csv file ", container = win)
csv.label <- glabel("csv with HDF's names ", container = csv.frame)
csv.file.name <- gfilebrowse("Select csv file", type="open",cont=csv.frame,action="read.csv")
dir.frame <- gframe("Output Directory ", container = win)
dir.label <- glabel("Where to save HDF's? ", container = dir.frame)
dir.out <- gfilebrowse("Select folder ",type = "selectdir", cont=dir.frame)
dlw.frame <- gframe("Download ", container = win)
dlw.label <- glabel(" ", container = dlw.frame)
btnDwn <- gbutton("Start Download", container = dlw.frame,
handler = function(csv.file.name,dir.out){
df <- read.csv(csv.file.name, header=TRUE,sep=",")
hdf.urls <- df$Online.Access.URLs
hdf.urls <- as.character(hdf.urls)
hdf.names <- df$Producer.Granule.ID
hdf.names <- as.character(hdf.names)
for (i in 1:length(hdf.names)){
URL <- hdf.urls [i]
file <- hdf.names[i]
download.file(URL,paste(dir.out,file,sep=""),mode="wb")
cat(paste("Composite number ",i,"successfully downloaded!"),sep="\n")
cat("\n\n\n\n\n\n\n\n")
}})
visible(win) <- TRUE
}
my.DownloadHDF()
I am using R-3.2.2 with RStudio 0.98.1103.
Here is the script after the improvements. Now it does exactly what I expect it to do. I hope someone finds it useful:
# load functions ####
# download function
f.d <- function(hdf.urls,hdf.names,out.dir){
for(i in 1:length(hdf.urls)){
URL <- hdf.urls [i]
file <- hdf.names [i]
download.file(URL,paste(out.dir,"/",file,sep=""),mode="wb")
}}
# read csv function
f.csv <- function(x){
df1 <<- read.csv(x,header=TRUE,sep=",")
hdf.urls <<- df1$Online.Access.URLs
hdf.urls <<- as.character(hdf.urls)
hdf.names <<- df1$Producer.Granule.ID
hdf.names <<- as.character(hdf.names)
}
# load functions ####
# my.DownloadHDFv2 this one works fine ####
my.DownloadHDF <- function(){
options(guiToolkit = "tcltk")
win <- gwindow("Download HDF with R!", visible = FALSE)
csv.frame <- gframe("csv with HDFs names ", container = win)
a <- gfilebrowse("Upload csv file",cont=csv.frame,
handler=function(h,...){
f.csv(svalue(a))
})
path.frame <- gframe("Output Directory ", container = win)
brow <- gfilebrowse(text = "Select folder...", type = "selectdir",container=path.frame,
handler=function(h,...){
out.dir <<- svalue(brow)
})
b <- gbutton(text="Start Download",container = win,
handler = function(h,...){
f.d(hdf.urls,hdf.names,out.dir=out.dir)
})
visible(win)<-TRUE
}
my.DownloadHDF()
# my.DownloadHDFv2 this one works fine ####

tcltk R - how to access value returned by function

I just started with tcltk and R. And I am having troubles accessing a computed value by a function called myFun1 when calling a second function myFun2:
Here is a simplified version of my UI:
Simple tcltk interface
library(tcltk)
tt <- tktoplevel()
topMenu <- tkmenu(tt)
tkconfigure(tt, menu = topMenu)
fileMenu <- tkmenu(topMenu, tearoff = FALSE)
tkadd(fileMenu, "command", label = "Function1", command = myFun1)
tkadd(fileMenu, "command", label = "Function2", command = myFun2)
tkadd(topMenu, "cascade", label = "Tab", menu = fileMenu)
tkfocus(tt)
My functions
myFun1 <- function() {
compVal <- 2*3
compVal
}
myFun2 <- function() {
msg <- paste("The value is: \n", compVal )
mbval<- tkmessageBox(title="This is the title",
message=msg,type="yesno",icon="question")
}
Calling myFun1 works, but myFun2 returns
Error in paste("The value is: \n", compVal) :
Object 'compVal' not found
Also wrapping compVal into return(compVal) doesn`t work.
I was also thinking of doing:
res <- list(compVal=compVal)
but I am not able to access the created list with myFun2.
Any sugesstions on how to access the returned value form myFun1 inside myFun2?
I found a solution, at first I thought its not really a "clean" way of doing it, but even in the offical documentation it is done this way.
Simply create a global variable using <<- :
myFun1 <- function() {
compVal <<- 2*3
}

Get data out of a tcltk function

This is probably so simple I will cringe when the answer comes back but I am totally stumped. I have tried the manuals, tried searching the web, assorted examples and anything else I can think of. I am still stuck.
I am trying to create a simple input for the user to add two values I can then use in the rest of the R script. I need the script to pause and wait for the input from the user and then continue along once it gets the input (like how the choose file function works). AFter reading a bunch of stuff I decided to use library(tcltk). I have a nice little box within a function.
inputs <- function(){
xvar <- tclVar("")
yvar <- tclVar("")
tt <- tktoplevel()
tkwm.title(tt,"Input Numbers")
x.entry <- tkentry(tt, textvariable=xvar)
y.entry <- tkentry(tt, textvariable=yvar)
reset <- function()
{
tclvalue(xvar)<-""
tclvalue(yvar)<-""
}
reset.but <- tkbutton(tt, text="Reset", command=reset)
submit <- function() {
x <- as.numeric(tclvalue(xvar))
y <- as.numeric(tclvalue(yvar))
print(x)
print(y)
tkdestroy(tt)
}
submit.but <- tkbutton(tt, text="submit", command=submit)
tkgrid(tklabel(tt,text="Enter Two Inputs"),columnspan=2)
tkgrid(tklabel(tt,text="Input1"), x.entry, pady = 10, padx =10)
tkgrid(tklabel(tt,text="Input2"), y.entry, pady = 10, padx =10)
tkgrid(submit.but, reset.but)
}
When I type in:
inputs()
The nice little box pops up and I can input my values, say 3 and 4 for this example.
I get back
<Tcl>
[1] 3
[1] 4
I want to use those number in a subsequent part of the R code. How do I get them so I can get the equivalent of this?
input1 <- 3
input2 <- 4
Thanks in advance for helping.
Here is a modification of your function:
inputs <- function(){
xvar <- tclVar("")
yvar <- tclVar("")
tt <- tktoplevel()
tkwm.title(tt,"Input Numbers")
x.entry <- tkentry(tt, textvariable=xvar)
y.entry <- tkentry(tt, textvariable=yvar)
reset <- function()
{
tclvalue(xvar)<-""
tclvalue(yvar)<-""
}
reset.but <- tkbutton(tt, text="Reset", command=reset)
submit <- function() {
x <- as.numeric(tclvalue(xvar))
y <- as.numeric(tclvalue(yvar))
e <- parent.env(environment())
e$x <- x
e$y <- y
tkdestroy(tt)
}
submit.but <- tkbutton(tt, text="submit", command=submit)
tkgrid(tklabel(tt,text="Enter Two Inputs"),columnspan=2)
tkgrid(tklabel(tt,text="Input1"), x.entry, pady = 10, padx =10)
tkgrid(tklabel(tt,text="Input2"), y.entry, pady = 10, padx =10)
tkgrid(submit.but, reset.but)
tkwait.window(tt)
return(c(x,y))
}
Now run the function like:
myvals <- inputs()
Now enter your 2 values and click "Submit", then look at the myvals variable, it contains your 2 values.
You have them in the submit callback -- you just need to put them somewhere. Sometimes global variables are best for this. Just use <<- to assign to them so the bindings happen outside of the scope of the submit callback. You can also use an environment for this purpose or even a reference class.

multiple comboboxes in R using tcltk

I have been trying to define multiple combo boxes in R using the tcltk package but to no avail. I am using the below code. My inspiration was here, however I can't seem to just label them comboBox1, comboBox2, etc... so I decided to try and set their output values into a vector... but their output values don't make any sense to me... any ideas out there?
many thanks
require(tcltk)
tclRequire("BWidget")
tt <- tktoplevel()
tkgrid(tklabel(tt,text="What's your favorite fruits?"))
fruit <- c("Apple","Orange","Banana","Pear")
num <- c(0:3)
num.fruit <- cbind(num, fruit)
#####1st box
comboBox <- tkwidget(tt,"ComboBox",editable=FALSE,values=num.fruit[,2])
tkgrid(comboBox)
Cbox1<- comboBox
tkfocus(tt)
######2nd box
comboBox <- tkwidget(tt,"ComboBox",editable=FALSE,values=num.fruit[,2])
tkgrid(comboBox)
Cbox2 <- comboBox
###
##preliminary wrap-ip to pass to OnOK function
pref1 <- tcl(Cbox1,"getvalue")
pref2 <- tcl(Cbox2,"getvalue")
Prefs <- c(pref1,pref2)
######action on OK button
OnOK <- function()
{
fruitChoice <- fruits[as.numeric(tclvalue(tcl(Prefs,"getvalue")))+1]
tkdestroy(tt)
msg <- paste("Good choice! ",fruitChoice,"s are delicious!",sep="")
tkmessageBox(title="Fruit Choice",message=msg)
}
OK.but <-tkbutton(tt,text=" OK ",command=OnOK)
tkgrid(OK.but)
tkfocus(tt)
Why don't you just use ttkcombobox?
require(tcltk)
tt <- tktoplevel()
tkwm.title(tt, "Fruits!")
tkwm.geometry(tt, "200x150+300+300")
onOK <- function()
{
fav <- tclvalue(favFruit)
worst <- tclvalue(worstFruit)
if (fav != "Choose one")
tkmessageBox(title="Favorite fruit", message = paste("Your favorite fruit is", fav))
if (worst != "Choose one")
tkmessageBox(title="Worst fruit", message = paste("The fruit you like the least is", worst))
if (fav == "Choose one" & worst == "Choose one")
tkmessageBox(title="Well...", message = "Select a fruit!")
}
label1 <- tklabel(tt, text="What's your favorite fruit?")
label2 <- tklabel(tt, text="What fruit you like the least?")
fruits <- c("Choose one", "Apple", "Orange", "Banana", "Pear")
# Default selections for the two combo boxes
favFruit <- tclVar("Choose one")
worstFruit <- tclVar("Choose one")
# 1st box
combo.1 <- ttkcombobox(tt, values=fruits, textvariable=favFruit, state="readonly")
# 2nd box
combo.2 <- ttkcombobox(tt, values=fruits, textvariable=worstFruit, state="readonly")
# If you need to do something when the user changes selection just use
# tkbind(combo.1, "<<ComboboxSelected>>", functionname)
OK.but <- tkbutton(tt,text=" OK ", command = onOK)
tkpack(label1, combo.1)
tkpack(label2, combo.2)
tkpack(OK.but)
tkfocus(tt)
PS: personally, I abandoned tcltk in favour of RGtk2, much more flexible in my opinion and you can design interfaces visually using Glade Interface Designer
If you don't want to get too involved with tcltk, you might find gWidgets easier to work with.
library(gWidgets)
options(guiToolkit="tcltk") ## or RGtk2 or Qt
w <- gwindow("Multiple comboboxes")
tbl <- glayout(cont=w, horizontal=FALSE)
fruit <- c("Apple","Orange","Banana","Pear")
tbl[1,1] <- "Favorite fuits"
tbl[1,2] <- (cb1 <- gcombobox(fruit, cont=tbl))
tbl[2,1] <- "Other fruit?"
tbl[2,2] <- (cb2 <- gcombobox(fruit, cont=tbl))
tbl[3,2] <- (b <- gbutton("Ok", cont=tbl))
addHandlerClicked(b, handler=function(h,...) {
cat(sprintf("You picked %s and %s\n", svalue(cb1), svalue(cb2)))
})

Resources