Thanks in advance for any help you can offer. I am trying to create a GUI that allows the user to choose choose which directory the files are located then input some other information. I then want to be able to calculate information like how many files are in the folder, and some other information that is gained from the files. I need the values that the user inputs to do any of the analysis. However, when I use svalue() I get an error. I also want to summarize the information on a second tab of the notebook. Here's my code so far:
library(gWidgets)
library(gWidgets2)
library(gWidgets2RGtk2)
library(gWidgetsRGtk2)
library(gWidgetstcltk)
library(gWidgets2tcltk)
library(pdftools)
require(gWidgets2RGtk2)
fileChoose <- function(action="print", text = "Select a file...",
type="open", ...) {
gfile(text=text, type=type, ..., action = action, handler =
function(h,...) {
do.call(h$action, list(h$file))
})
}
path <- fileChoose(action="setwd", type="selectdir", text="Select a
directory...")
files <- list.files(path, full.names = TRUE)
files_ex <- file_ext(files)
win <- gwindow("DataMate Project")
grp <- ggroup(horizontal = FALSE, container=win)
nb <- gnotebook(container = grp, expand=TRUE)
group1 <- ggroup(horizontal = FALSE, container=nb, label = "Input")
x <- c("SELECT CUSTOMER", "Eaton", "NG", "Spectris", "Other")
n <- length(files_ex)
lyt <- glayout(cont = frame)
glabel("File Path to Docs", container = group1)
p <- gedit(path, container=group1)
glabel("To your knowledge is this an ITAR quote?", container = group1)
itar <- gradio(c("Non-ITAR","ITAR"), container=group1)
glabel("Who is the customer? (Parent company)", container = group1)
cust <- gcombobox(x, container=group1)
glabel("How many RFQs / Assemblies?", container = group1)
val <- gspinbutton(from=1, to = 100, by =1, value=1,container=group1)
run <- gbutton("Run", container = group1, gmessage(svalue(val))
Maybe this will get you a start:
show_gui <- function(parent, path) {
files <- list.files(path, full.names = TRUE)
files_ex <- tools::file_ext(files)
nb <- gnotebook(container = parent, expand=TRUE)
group1 <- gframe(horizontal = FALSE, container=nb, label = "Input", expand=TRUE)
x <- c("SELECT CUSTOMER", "Eaton", "NG", "Spectris", "Other")
n <- length(files_ex)
glabel("File Path to Docs", container = group1)
p <- gedit(path, container=group1)
glabel("To your knowledge is this an ITAR quote?", container = group1)
itar <- gradio(c("Non-ITAR","ITAR"), container=group1)
glabel("Who is the customer? (Parent company)", container = group1)
cust <- gcombobox(x, container=group1)
glabel("How many RFQs / Assemblies?", container = group1)
val <- gspinbutton(from=1, to = 100, by =1, value=1,container=group1)
run <- gbutton("Run", container = group1, handler = function(h, ...) {
gmessage(svalue(val))
})
}
w <- gwindow("GUI")
parentgroup <- ggroup(cont=w)
g = ggroup(cont=parentgroup, horizontal=FALSE)
glabel("Choose a file to proceed", cont=g)
gfilebrowse(cont=g, type="selectdir", handler=function(h, ...) {
dname = svalue(h$obj)
if (dir.exists(dname)) {
delete(parentgroup, g)
show_gui(parentgroup, dname)
} else {
gmessage("That file does not exists")
}
})
You had several mistakes. I didn't do the rest for you, but in the button handler you would create the widgets in a new tab, and use svalue(nb) <- 2 to switch to that tab.
1) I used the package gWidget to make a GUI in R. I have had some problems. I want to add a "save" button in the window, but I don't know how to store the pic already drawn in ggraphics.
library("memoise")
library("gWidgets2RGtk2")
library("RGtk2")
library("digest")
library("gWidgets2")
library("stats")
options(guiToolkit="RGtk2")
d<-0
#the main window to make and some parts of it to make
win <- gwindow("Load curve analysis", visible=TRUE,expand = TRUE)
biggroup <- ggroup(horizontal = FALSE, container=win, expand = TRUE)
topgroup<-ggroup(horizontal = TRUE, container=biggroup,expand = TRUE)
bottomgroup<-ggroup(horizontal = TRUE, container=biggroup, expand = TRUE)
leftgroup<-ggroup(horizontal = FALSE, container=bottomgroup,expand= TRUE)
rightgroup<-ggroup(horizontal = FALSE, container=bottomgroup,expand=TRUE)
add(rightgroup, ggraphics(), expand=TRUE)
#draw a pic
updatePlot <- function(h,...) {
if(d==1){
if(svalue(Analyse1)=="Month duration curve")
plot(1:100,1:100,main="1")
if(svalue(Analyse1)=="Month load curve")
plot(1:100,1:100,main="2")
}
if(d==2){
if(svalue(Analyse2)=="Jahresdauerlinie"){
plot(1:100,1:100,main="3")
}
}
}
#the "save" button to make, this button will bring another window,
#but after setting up the road of the saving place, this smaller window will be closed
Store<-gbutton("Save as pdf",container=topgroup, handler = function(h,...){
win1 <- gwindow("set up road", visible=TRUE,expand = TRUE)
group <- ggroup(horizontal = FALSE, container=win1, expand = TRUE)
tmp <- gframe("Pls type the place you want to save in", container=group)
obj0<-gedit("",cont=tmp,expand = TRUE)
tmp <- gframe("Pls name the new diagram, and end it with .pdf", container=group)
obj1<-gedit("Lastganganalyse.pdf",cont=tmp,expand = TRUE)
#here the function recordPlot will be used,but it doesnt work,the document cant be opened
ok<-gbutton("Ok",container=group, handler = function(h,...){
p<-recordPlot()
# I dont know why this record Plot doesnt work
setwd(svalue(obj0))
pdf(svalue(obj1))
p
dev.off()
dispose(win1)
})
})
#the other parts of the main window
tmp <- gframe("Year(after input a year pls press Enter)", container=leftgroup)
#Jahren <- gradio(c(2012,2013,2014), horizontal=FALSE, cont=tmp, handler=updatePlot)
Jahren<-gedit("2012",cont=tmp, handler=updatePlot)
tmp <- gframe("Month", container=leftgroup)
Monat <- gslider(from=1,to=12,by=1, value=1, cont=tmp, handler=updatePlot)
tmp <- gframe("Analysis' way of a month", container=leftgroup)
Analyse1 <- gcombobox(c(" ","Month duration curve","Month load curve"), cont=tmp, handler=function(h,...){
d<<-1
updatePlot(h,...)
},expand = TRUE)
tmp <- gframe("Analysis' way of a year", container=leftgroup)
Analyse2 <- gcombobox(c(" ","Jahresdauerlinie"),cont=tmp,handler=function(h,...){
d<<-2
updatePlot(h,...)},expand = TRUE)
2) Besides, I don't know how to set up the size of the ggroup. Or how can I control all parts of the window's size to look better. I dont know that kind of function.
3) The line which is drawn in ggraphics is hard to be seen. And how can I change this situation?
Suppose we had the following plot in the graphics:
ggplot(dat = data.frame("x" = 1:100, "y" = rnorm(100)), aes(x = x, y = y)) + geom_point()
Within the handler for the button, you can try the following:
setwd(svalue(obj0))
dev.copy2pdf(file = svalue(obj1))
I am trying to create an interactive histogram in R whose bin width can be adjusted either by moving a slider or entering a value in the text box. In addition to this, I would also like to provide the user with an option of saving the plot for a particular bin width.
To this end, I found the 'gslider' function of 'aplpack' library to be a good starting point. I tried to modify it to meet my purpose as well as learn more about Tcl/Tk constructs. But I am now stuck and can't proceed, mostly because I haven't completely understood how a slider value is captured and transferred between functions.
Following are the snippets of code that I haven't really understood. These are from the source code of the 'gslider' function.
# What is the rationale behind using the 'assign' function here and at
# other instances in the code?
img <- tkrplot::tkrplot(gr.frame, newpl, vscale = 1, hscale = 1)
tkpack(img, side = "top")
assign("img", img, envir = slider.env)
# I understand the below lines when considered individually. But collectively,
# I am having a difficult time comprehending them. Most importantly, where
# exactly is the slider movement captured here?
sc <- tkscale(fr, from = sl.min, to = sl.max,
showvalue = TRUE, resolution = sl.delta, orient = "horiz")
assign("sc", sc, envir = slider.env)
eval(parse(text = "tkconfigure(sc, variable=inputbw1)"), envir = slider.env)
sl.fun <- sl.function
if (!is.function(sl.fun))
sl.fun <- eval(parse(text = paste("function(...){",
sl.fun, "}")))
fname <- 'tkrrsl.fun1'
eval(parse(text = c(paste(fname, " <-"), " function(...){",
"tkrreplot(get('img',envir=slider.env),fun=function()",
deparse(sl.fun)[-1], ")", "}")))
eval(parse(text = paste("environment(", fname, ")<-parent.env")))
if (prompt)
tkconfigure(sc, command = get(fname))
else tkbind(sc, "<ButtonRelease>", get(fname))
if (exists("tkrrsl.fun1")) {
get("tkrrsl.fun1")()
}
assign("slider.values.old", sl.default, envir = slider.env)
Thanks to everyone for the varied scope of answers. Juba's and Greg's answers were the ones I could work upon to write the following code:
slider_txtbox <- function (x, col=1, sl.delta, title)
{
## Validations
require(tkrplot)
pos.of.panel <- 'bottom'
if(is.numeric(col))
col <- names(x)[col]
x <- x[,col, drop=FALSE]
if (missing(x) || is.null(dim(x)))
return("Error: insufficient x values")
sl.min <- sl.delta # Smarter initialization required
sl.max <- max(x)
xrange <- (max(x)-min(x))
sl.default <- xrange/30
if (!exists("slider.env")) {
slider.env <<- new.env(parent = .GlobalEnv)
}
if (missing(title))
title <- "Adjust parameters"
## Creating initial dialogs
require(tcltk)
nt <- tktoplevel()
tkwm.title(nt, title)
if(.Platform$OS.type == 'windows')
tkwm.geometry(nt, "390x490+0+10")
else if(.Platform$OS.type == 'unix')
tkwm.geometry(nt, "480x600+0+10")
assign("tktop.slider", nt, envir = slider.env)
"relax"
nt.bak <- nt
sl.frame <- tkframe(nt)
gr.frame <- tkframe(nt)
tx.frame <- tkframe(nt)
tkpack(sl.frame, tx.frame, gr.frame, side = pos.of.panel)
## Function to create and refresh the plot
library(ggplot2)
library(gridExtra)
makeplot <- function(bwidth, save) {
if(bwidth <= 0) {
df <- data.frame('x'=1:10, 'y'=1:10)
histplot <- ggplot(df, aes(x=x, y=y)) + geom_point(size=0) + xlim(0, 10) + ylim(0, 100) +
geom_text(aes(label='Invalid binwidth...', x=5, y=50), size=9)
} else {
histplot <- ggplot(data=x, aes_string(x=col)) +
geom_histogram(binwidth=bwidth, aes(y = ..density..), fill='skyblue') +
theme(axis.title.x=element_text(size=15), axis.title.y=element_text(size=15),
axis.text.x=element_text(size=10, colour='black'),
axis.text.y=element_text(size=10, colour='black'))
}
print(histplot)
if(save){
filename <- tkgetSaveFile(initialfile=paste('hist_bw_', bwidth, sep=''),
filetypes='{{PNG files} {.png}} {{JPEG files} {.jpg .jpeg}}
{{PDF file} {.pdf}} {{Postscript file} {.ps}}')
filepath <- as.character(filename)
splitpath <- strsplit(filepath, '/')[[1]]
flname <- splitpath[length(splitpath)]
pieces <- strsplit(flname, "\\.")[[1]]
ext <- tolower(pieces[length(pieces)])
if(ext != 'png' && ext != 'jpeg' && ext != 'jpg' && ext != 'pdf' && ext != 'ps') {
ext <- 'png'
filepath <- paste(filepath, '.png', sep='')
filename <- tclVar(filepath)
}
if(ext == 'ps')
ext <- 'postscript'
eval(parse(text=paste(ext, '(file=filepath)', sep='')))
eval(parse(text='print(histplot)'))
dev.off()
}
}
img <- tkrplot::tkrplot(gr.frame, makeplot(sl.default, FALSE), vscale = 1, hscale = 1)
tkpack(img, side = "top")
assign("img", img, envir = slider.env)
## Creating slider, textbox and labels
parent.env <- sys.frame(sys.nframe() - 1)
tkpack(fr <- tkframe(sl.frame), side = 'top')
sc <- tkscale(fr, from = sl.min, to = sl.max,
showvalue = TRUE, resolution = sl.delta,
orient = "horiz")
tb <- tkentry(fr, width=4)
labspace <- tklabel(fr, text='\t\t\t')
tkpack(sc, labspace, tb, side = 'left')
tkpack(textinfo <- tkframe(tx.frame), side = 'top')
lab <- tklabel(textinfo, text = ' Move slider', width = "20")
orlabel <- tklabel(textinfo, text=' OR', width='10')
txtboxmsg <- tklabel(textinfo, text = 'Enter binwidth', width='20')
tkpack(txtboxmsg, orlabel, lab, side='right')
tkpack(f.but <- tkframe(sl.frame))
tkpack(tklabel(f.but, text=''))
tkpack(tkbutton(f.but, text = "Exit", command = function() tkdestroy(nt)),
side='right')
tkpack(tkbutton(f.but, text = "Save", command = function(...) {
bwidth <- as.numeric(tclvalue(get('inputtb', envir=slider.env)))
tkrreplot(get('img',envir=slider.env),fun=function() { makeplot(bwidth, TRUE); sync_slider()})
}), side='right')
## Creating objects and variables associated with slider and textbox
assign("sc", sc, envir = slider.env)
eval(parse(text = "assign('inputsc', tclVar(sl.default), envir=slider.env)"))
eval(parse(text = "tkconfigure(sc, variable=inputsc)"), envir = slider.env)
assign("tb", tb, envir = slider.env)
eval(parse(text = "assign('inputtb', as.character(tclVar(sl.default)),
envir=slider.env)"))
eval(parse(text = "tkconfigure(tb, textvariable=inputtb)"), envir = slider.env)
## Function to update the textbox value when the slider has changed
sync_textbox <- function() {
bwidth_sl <- tclvalue(get('inputsc', envir=slider.env))
assign('inputtb', tclVar(bwidth_sl), envir=slider.env)
eval(parse(text = "tkconfigure(tb, textvariable=inputtb)"), envir = slider.env)
}
## Function to update the slider value when the textbox has changed
sync_slider <- function() {
bwidth_tb <- tclvalue(get('inputtb', envir=slider.env))
assign('inputsc', tclVar(bwidth_tb), envir=slider.env)
eval(parse(text = "tkconfigure(sc, variable=inputsc)"), envir = slider.env)
}
## Bindings : association of certain functions to certain events for the slider
## and the textbox
tkbind(sc, "<ButtonRelease>", function(...) {
bwidth <- as.numeric(tclvalue(get('inputsc', envir=slider.env)))
tkrreplot(get('img',envir=slider.env),fun=function() { makeplot(bwidth, FALSE); sync_textbox()})
})
tkbind(tb, "<Return>", function(...) {
bwidth <- as.numeric(tclvalue(get('inputtb', envir=slider.env)))
if(bwidth > sl.max && !is.na(bwidth)) {
bwidth <- sl.max
assign('inputtb', tclVar(bwidth), envir=slider.env)
eval(parse(text = "tkconfigure(tb, textvariable=inputtb)"), envir = slider.env)
} else
if(bwidth < sl.min || is.na(bwidth)) {
bwidth <- sl.min
assign('inputtb', tclVar(bwidth), envir=slider.env)
eval(parse(text = "tkconfigure(tb, textvariable=inputtb)"), envir = slider.env)
}
tkrreplot(get('img',envir=slider.env),fun=function() { makeplot(bwidth, FALSE); sync_slider()})
})
}
library(ggplot2)
slider_txtbox(movies, 'rating', 0.1, 'Adjust binwidth')
Here is a minimal working example with comments, based on the complete code you first submit. As I'm far from an expert in tcl/tk, there may be cleaner or better ways to do it. And it is quite incomplete (for example the textbox values should be checked to be in the range of the slider, etc.) :
library(ggplot2)
library(gridExtra)
title <- "Default title"
data(movies)
## Init dialog
require(tkrplot)
if (!exists("slider.env")) slider.env <<- new.env(parent = .GlobalEnv)
require(tcltk)
nt <- tktoplevel()
tkwm.title(nt, title)
tkwm.geometry(nt, "480x600+0+10")
assign("tktop.slider", nt, envir = slider.env)
"relax"
nt.bak <- nt
sl.frame <- tkframe(nt)
gr.frame <- tkframe(nt)
tx.frame <- tkframe(nt)
tkpack(sl.frame, tx.frame, gr.frame, side = "bottom")
## First default plot
newpl <- function(...) {
dummydf <- data.frame('x'=1:10, 'y'=1:10)
dummy <- ggplot(dummydf, aes(x=x, y=y)) + geom_point(size=0) + xlim(0, 10) + ylim(0, 100) +
geom_text(aes(label='Generating plot...', x=5, y=50), size=9)
print(dummy)
}
img <- tkrplot::tkrplot(gr.frame, newpl, vscale = 1, hscale = 1)
tkpack(img, side = "top")
assign("img", img, envir = slider.env)
tkpack(fr <- tkframe(sl.frame), side = 'top')
## Creating slider, textbox and labels
sc <- tkscale(fr, from = 0, to = 5, showvalue = TRUE, resolution = 0.1, orient = "horiz")
tb <- tkentry(fr, width=4)
lab <- tklabel(fr, text = 'Select binwidth ', width = "16")
orlabel <- tklabel(fr, text=' or ', width='4')
tkpack(lab, sc, orlabel, tb, side = 'left')
tkpack(textinfo <- tkframe(tx.frame), side = 'top')
## Creating objects and variables associated with slider and textbox
assign("sc", sc, envir = slider.env)
assign("tb", tb, envir = slider.env)
assign('inputsc', tclVar(2.5), envir=slider.env)
assign('inputtb', tclVar('2.5'), envir=slider.env)
eval(parse(text = "tkconfigure(sc, variable=inputsc)"), envir = slider.env)
eval(parse(text = "tkconfigure(tb, textvariable=inputtb)"), envir = slider.env)
## Function to update the textbox value when the slider has changed
sync_textbox <- function() {
bwidth_sl <- tclvalue(get('inputsc', envir=slider.env))
assign('inputtb', tclVar(bwidth_sl), envir=slider.env)
eval(parse(text = "tkconfigure(tb, textvariable=inputtb)"), envir = slider.env)
}
## Function to update the slider value when the textbox has changed
sync_slider <- function() {
bwidth_tb <- tclvalue(get('inputtb', envir=slider.env))
assign('inputsc', tclVar(bwidth_tb), envir=slider.env)
eval(parse(text = "tkconfigure(sc, variable=inputsc)"), envir = slider.env)
}
## Function to refresh the plot
refresh <- function(bwidth) {
histplot <- ggplot(data=movies, aes_string(x="rating")) +
geom_histogram(binwidth=bwidth,
aes(y = ..density..), fill='skyblue') +
theme(axis.title.x=element_text(size=15), axis.title.y=element_text(size=15),
axis.text.x=element_text(size=10, colour='black'),
axis.text.y=element_text(size=10, colour='black'))
print(histplot)
}
## Bindings : association of certain functions to certain events for the slider
## and the textbox
tkbind(sc, "<ButtonRelease>", function(...) {
bwidth <- as.numeric(tclvalue(get('inputsc', envir=slider.env)))
tkrreplot(get('img',envir=slider.env),fun=function() { refresh(bwidth); sync_textbox()})
})
tkbind(tb, "<Return>", function(...) {
bwidth <- as.numeric(tclvalue(get('inputtb', envir=slider.env)))
tkrreplot(get('img',envir=slider.env),fun=function() { refresh(bwidth); sync_slider()})
})
If you do not insist on a local solution, you might give rapporter.net a try, which lets you specify such tasks easily with any number of tweakable sliders. Okay, enough of marketing :)
Here goes a quick demo: Interactive histogram on mtcars which looks like:
There you could choose one of the well-know variables of mtcars, but of course you could provide any data frame to be used here or tweak the above form after a free registration.
How it's done? I have just created a quick rapport template and let it rapplicate. The body of the template is written in brew-style (please see the above "rapport" URL for more details):
<%=
evalsOptions('width', width)
evalsOptions('height', height)
%>
# Histogram
<%=
set.caption(paste('Histogram of', var.name))
hist(var, breaks=seq(min(var), max(var), diff(range(var))/round(binwidth)), main = paste('Histogram of', var.name), xlab = '')
%>
## Parameters
Provided parameters were:
* variable: <%=var.name%> (<%=var.label%>)
* bin-width of histogram: <%=binwidth%>
* height of generated images: <%=height%>
* width of generated images: <%=width%>
# Kernel density plot
<%=
set.caption('A kernel density plot')
plot(density(var), main = '', xlab = '')
%>
But a bare-minimal example of the task could be also addressed by a simple one-liner template:
<%=hist(var, breaks=seq(min(var), max(var), diff(range(var))/round(binwidth)))%>
There you would only need to create a new template, add two input types with a click (one numeric variable of any data set and a number input field which would hold the binwidth of the histogram), and you are ready to go.
You might want to look at the R package 'rpanel' -- it uses tcltk under the hood but is much simpler to use:
rpanel
rpanel reference
I don't know the gslider function and cannot help you there, but here are some alternatives:
One simple option is to use the tkexamp function from the TeachingDemos package, here is one way:
library(TeachingDemos)
myhist <- function(x, s.width, e.width, ...) {
if( missing(e.width) || is.null(e.width) || is.na(e.width) ) {
e.width<- s.width
}
b <- seq( min(x)-e.width/2, max(x)+e.width, by=e.width )
hist(x, b, ...)
}
mylist <- list( s.width=list('slider', init=1, from=1, to=10, resolution=1),
e.width=list('numentry', init='', width=7)
)
sampdata <- rnorm(100, 50, 5)
tkexamp(myhist(sampdata), mylist)
This will create a quick GUI with your histogram and a slider and entry widget. The width of the bars are determined by the value in the entry widget, and if that is blank (default) then the value of the slider. Unfortunately the slider and entry widget do not update each other. There is a button that will print out the current call, so the same plot can be recreated from the command line in the default or current plotting device. You can edit the mylist variable above to make the controls fit your data better.
If you want the entry and slider to update each other then you can program that more directly. Here is a basic function that uses tkrplot:
mytkhist <- function(x, ...) {
width <- tclVar()
tclvalue(width) <- 1
replot <- function(...) {
width <- as.numeric(tclvalue(width))
b <- seq( min(x) - width/2, max(x)+width, by=width )
hist(x,b,...)
}
tt <- tktoplevel()
img <- tkrplot(tt, replot)
tkpack(img, side='top')
tkpack( tkscale(tt, variable=width, from=1, to=10,
command=function(...) tkrreplot(img),
orient='horizontal'), side='top' )
tkpack( e <- tkentry(tt, textvariable=width), side='top' )
tkbind(e, "<KeyRelease>", function(...) tkrreplot(img))
}
mytkhist(sampdata)
The fact that both the slider (scale) and the entry widget use the same variable is what makes them automatically update each other (no calls to assign needed). The command argument in tkscale and the tkbind call mean that any changes to either the slider or the entry will update the plot. This does not have anything to save the current plot, but you should be able to add that part as well as any other controls that you want to use.
In the widget below, is it possible to change the position of the label of the "radio" groups. I would like something like that instead of having "Type" above the items:
Type o Quantitative
o Qualitative
win <- gwindow("Empirical Phase Diagram")
BigDataGroup <- ggroup(cont=win)
DataGroup <- gframe("Data", container = BigDataGroup, horizontal=FALSE)
grp.file <- ggroup(horizontal=FALSE, container = DataGroup)
lbl.file <- glabel("File: ", container = grp.file)
browse.file <- gfilebrowse(container = grp.file)
Input1Group <- gframe("First input variable ", container = DataGroup, horizontal=FALSE)
grp.text.input1 <- ggroup(horizontal=FALSE, container = Input1Group)
lbl.text.input1 <- glabel("Column index", container = grp.text.input1)
insert.text.input1 <- gedit(text="A", container = grp.text.input1)
grp.type.input1 <- ggroup(horizontal=FALSE, container = Input1Group)
#addSpring(grp.type.input1)
lbl.type.input1 <- glabel("Type ", container = grp.type.input1)
insert.type.input1 <- gradio(items=c("Quantitative", "Qualitative"), container = grp.type.input1)
Input2Group <- gframe("Second input variable ", container = DataGroup, horizontal=FALSE)
grp.text.input2 <- ggroup(horizontal=FALSE, container = Input2Group)
lbl.text.input2 <- glabel("Column index", container = grp.text.input2)
insert.text.input2 <- gedit(text="B", container = grp.text.input2)
grp.type.input2 <- ggroup(horizontal=FALSE, container = Input2Group)
lbl.type.input2 <- glabel("Type ", container = grp.type.input2)
insert.type.input2 <- gradio(items=c("Quantitative", "Qualitative"), container = grp.type.input2)
grp.text.output <- ggroup(horizontal=FALSE, container = DataGroup)
lbl.text.output <- glabel("Output variable range ", container = grp.text.output)
insert.text.output <- gedit(initial.msg="type a range e.g. C:AD", container = grp.text.output)
OptionsGroup <- ggroup(horizontal=FALSE, container = BigDataGroup)
grp.colorspace <- ggroup(horizontal=FALSE, container = OptionsGroup)
insert.colorspace <- gradio(items=c("RGB", "LAB", "LUV"))
lbl.colorspace <- gframe("Color space ", container = grp.colorspace)
add(lbl.colorspace, insert.colorspace)
GoGroup <- ggroup(horizontal=FALSE, container = BigDataGroup)
addSpring(GoGroup)
read <- gbutton(text="Go", container = GoGroup,
handler = function(h, ...) {
print(EPD(filename=svalue(browse.file),
input1=svalue(insert.text.input1),
input2=svalue(insert.text.input2),
outputs=svalue(insert.text.output),
color.space=svalue(insert.colorspace))
)
}
)
Two things:
In gWidgets you can use a glayout container to put labels on the left. Something like:
tbl <- glayout(cont=parent_container)
tbl[1,1] <- "Type" ## or glabel("Type ", container = tbl)
tbl[1,2] <- (insert.type.input1 <- gradio(items=c("Quantitative", "Qualitative"), container = tbl))
The latter double assignment gives you access to the radio widget. You can also get this with tbl[1,2]. This works fine, but you need to do some bookkeeping for the row index.
In gWidgets2 (on github only right now) there is also the gformlayout container which makes this easier:
flyt <- gformlayout(cont=parent_container)
insert.type.input1 <- gradio(items=c("Quantitative", "Qualitative"),
horizontal=FALSE,
label = "Type", container = flyt)
As an aside, if you are using gWidgets2RGtk2 you can modify the font of this label, but it is super hacky. E.g.:
get_labels <- function(fl) {
children <- Map(function(x) x$getWidget(), fl$widget$getChildren())
labels <- Filter(function(x) is(x, "GtkLabel"), children)
names(labels) <- sapply(labels, function(x) x$getText())
labels
}
## Then to set the font of a label you can do:
labels <- get_labels(flyt)
flyt$set_rgtk2_font(labels[["Type"]], list(weight="bold"))
And, if you are still using tcltk, this function should work:
set_formlayout_font <- function(fl, value, row) {
l = tcl("grid", "slaves", fl$widget, row=row-1, column=0)
fl$set_font_ttk(value, l)
}
set_formlayout_font(fl, list(color="blue"), 2) ## 2nd row
I am writing a GUI with the gwidgets package in R. I am implementing a tool that will allow the user to select a number of variables from one list, and drag them to an empty list for collection. The inspiration is the gui from SPSS, see link:
spss drag and drop
I was planning do this with two gtables, i.e. first create one gtable with the list of variables, and an empty gtable to collect the selected variables. Below is my sample code:
portfolioBuilder <- function(h,...){
## globals
widgets <- list()
varNames <- c("var1","var2","var3","var4" )#with(.GlobalEnv, names(data))
#window
win <- gwindow("Test")
#groups
g <- ggroup(horizontal = FALSE, container = win, expand = TRUE)
gg <- ggroup(horizontal = FALSE, container = win, expand = TRUE)
#graphics container
ggraphics(container = gg)
#paned group
pg <- gpanedgroup(container = g, expand = TRUE)
nb <- gnotebook(container = pg)
## main group
qpg <- ggroup(horizontal = FALSE, container = nb, label = "portfolio")
parg <- ggroup(horizontal = FALSE, container = nb, label = "portfolio args")
## qplot group
tbl <- glayout(container = qpg)
#variable list
tbl[1,1,anchor = c(1,0)] <- "Variables"
tbl[2:10,2] <- (widgets[["table"]] <- gtable(varNames, multiple = TRUE, container = tbl, expand = TRUE))
tbl[3,3, anchor = c(1,0)] <- "y"
tbl[3,4] <- (widgets[["y"]] <- gedit("", container = tbl))
tbl[4,3, anchor = c(1,0)] <- "x"
tbl[4,4] <- (widgets[["x"]] <- gtable(c(""),container = tbl))
## make table visible and set tab
visible(tbl) <- TRUE
svalue(nb) <- 1
##################################end layout#################################
}
However my sample code spits out an error because of the empty gtable widget. Does anyone know how to accomplish this with gwidgets?
You'll want to work on the layout, but the key to this is addDropSource and addDropTarget:
options(guiToolkit="RGtk2")
library(gWidgets)
w <- gwindow(visible=FALSE)
g <- gpanedgroup(cont=w)
tbl <- gtable(names(mtcars), cont=g)
fl <- gframe("variables", horizontal=FALSE, cont=g)
dep <- gedit(initial.msg="Dependent variable", label="Dependent", cont=fl)
ind <- gedit(initial.msg="Independent variable(s)", label="Independent", cont=fl)
addDropSource(tbl, handler=function(h,...) svalue(h$obj))
addDropTarget(dep, handler=function(h,...) svalue(h$obj) <- h$dropdata)
addDropTarget(ind, handler=function(h,...) {
cur <- svalue(h$obj)
new <- ifelse(nchar(cur) > 0, paste(cur, h$dropdata, sep=", "), h$dropdata)
svalue(h$obj) <- new
})
visible(w) <- TRUE
Drag and drop support in gWidgets is really variable. Of the 6 possibilities for this to work in: gWidgetsRGtk2, gWidgets2RGtk2, gWidgetstcltk, gWidgets2tcltk, gWidgetsQt and gWidgets2Qt this code only worked in gWidgetsRGtk2.