How should I handle the situation in the gWidgets example below?
What I am trying to achieve with this little graphical user interface is to have a sub window that can be updated. It works well. However, if the user close the 'Click history' window by clicking the 'X' an error arise:
Error: attempt to call 'GetBuffer' on invalid reference 'view'
It seem that the reference/pointer to the sub window is lost. I have tried various strategies to solve the problem. For example to use tryCatch and re-create the window. That resulted in a new window opened for every click. Can the reference be retained somehow?
Update: I'm using R 3.2.2 and the gWidgetsRGtk2 toolkit on a Windows 7 system.
mainWindow <- function(){
require(gWidgets)
# This works well until the log window is closed.
# Next click gives this error:
# Error: attempt to call 'GetBuffer' on invalid reference 'view'
w_main <- gwindow(title="Main", visible=TRUE)
b_time <- gbutton("Show time!", container=w_main)
w_time <- gwindow(title="Click history", visible=FALSE)
t_time <- gtext("", container=w_time)
addHandlerChanged(b_time, handler = function(h, ...) {
# Log click.
insert(t_time, paste(date()))
# Show window.
visible(w_time) <- TRUE
} )
}
Update2: Implementation according to jverzani's suggestion seem to work fine. In fact I have tried something similar, but I think I forgot the <<-
mainWindow <- function(){
require(gWidgets)
# This works well also when the log window has been closed!
w_main <- gwindow(title="Main", visible=TRUE)
b_time <- gbutton("Show time!", container=w_main)
w_time <- gwindow(title="Click history", visible=FALSE)
t_time <- gtext("", container=w_time)
closed <- FALSE
addHandlerChanged(b_time, handler = function(h, ...) {
if(closed){
# Re-create window.
w_time <<- gwindow(title="Click history", visible=FALSE)
t_time <<- gtext("", container=w_time)
closed <<- FALSE
}
# Log click.
insert(t_time, paste(date()))
# Show window.
visible(w_time) <- TRUE
} )
addHandlerDestroy(w_time, handler = function(h, ...) {
# Subwindow closed!
closed <<- TRUE
} )
}
Here is the solution as provided by #jverzani
mainWindow <- function(){
require(gWidgets)
# This works well also when the log window has been closed!
w_main <- gwindow(title="Main", visible=TRUE)
b_time <- gbutton("Show time!", container=w_main)
w_time <- gwindow(title="Click history", visible=FALSE)
t_time <- gtext("", container=w_time)
addHandlerChanged(b_time, handler = function(h, ...) {
if(!isExtant(w_time)){
# Re-create window.
w_time <<- gwindow(title="Click history", visible=FALSE)
t_time <<- gtext("", container=w_time)
}
# Log click.
insert(t_time, paste(date()))
# Show window.
visible(w_time) <- TRUE
} )
}
Related
I am trying to put several ginputs into a form in gWidgets2, or to get the text entered in a gedit widget as a list or something to use in the rest of the code,
library(gWidgets2)
options(guiToolkit = "tcltk")
prj_name = ginput("Project name")
user = ginput("User name")
transfer = ginput("Transfer amount")
I tried with gformlayout but they ginput apparently can't be contained in one; and I haven't found how to pass the inputs on the widget to an object (a list in this case) in R
ginput is a dialog. The widget you want is gedit. This example is from the help page of gformlayout
w <- gwindow("gformlayout", visible=FALSE)
g <- gvbox(container=w)
flyt <- gformlayout(container=g)
gedit("", label="Name:", container=flyt)
gedit("", label="Rank:", container=flyt)
gedit("", label="Serial No.:", container=flyt)
b <- gbutton("Show me", container=g, handler=function(h,...) {
print(svalue(flyt))
})
addSpring(g)
visible(w) <- TRUE
I have developed a graphical user interface (GUI) in R using gWidgets. Here is some lines of the code:
library(gWidgets)
library(rattle)
library(RGtk2)
library(tcltk)
## Draw main window:
main_win <- gwindow("Advanced FFDFS: 4-day & 8-day forest fire danger
forecasting ", visible= FALSE, toolkit = guiToolkit())
paned <- gpanedgroup ( cont = main_win )
###########
group <- ggroup(horizontal = FALSE, container=paned)
###########
## Adding logo to the Manin Window
frame_1 <- gframe ( "" , cont = group , horizontal = FALSE )
Here, you could see the GUI:
https://www.dropbox.com/s/8wjng4ukfch9t9y/GUI.jpg?dl=0
Everything is Okay, and by hitting "Run", the program starts to work. All the process is showing in R console.
My question:
Is there any way to invoke R console contents to be shown in the developed graphical user interface (GUI)?
Something like this:
https://www.dropbox.com/s/kb6m3sex02g53qj/GUI2.jpg?dl=0
Reason?
The reason why I want to have this in the GUI is that:
1- Users can see what is going on without looking to the R/R-studio.
2- I want to schedule the program to be run everyday (which is another challenge for me later on), so users do not open the R/R-studio.
Any comment or thought would be highly appreciated.
A simple code based on #jverzani comment:
## Draw main window:
main_win <- gwindow("Adv", visible= FALSE, toolkit = guiToolkit())
button.group_run <- ggroup(container = main_win)
## Push buttons to right
addSpring(button.group_run)
obj_run <- gbutton("Run", container=button.group_run,
handler = function(h,...) gmessage("Good, let me run the model"))
obj_cancel <- gbutton("Cancel", handler = function(h,...) dispose(main_win),
container=button.group_run)
obj_help <- gbutton("Help", container=button.group_run,
handler = function(h,...) gmessage("Test"))
visible ( main_win ) <- TRUE
## Do these when user clicks on Run button:
addhandlerchanged(obj_run, handler=function(h,...)
{
r_console_aa <- capture.output(
print("What is your Username?")
print("NA")
getwd()
)
r_console_aa
})
r_console_aa
I have been building application in R with gWidgets.
Application includes several editable tables, working sheets etc - basically works something like MS Excell, but for special purpose.
When the user will save the work done and exit application, he/she should be able to continue working from where he/she ended - something like clicking on the icon or importing "working document" into the application - so that all sheets and data will be opened (again something like MS Excell etc.) and the same as they were when application was closed.
However, I have no idea how to do that. Can anyone help?
Some pattern like this should work:
library(gWidgets2)
# Global variables
widgets <- list()
values <- NULL # or a list()
state <- NULL
## Layout GUI
w <- gwindow("Test")
g <- ggroup(cont=w)
g1 <- ggroup(horizontal=FALSE, cont=g)
save_btn <- gbutton("Save state", cont=g1)
restore_btn <- gbutton("restore state", cont=g1)
widgets$w1 = gedit("some text", cont=g)
nb = gnotebook(cont=g)
widgets$w2 = gradio(c("a","b","c"), label="radio", cont=nb)
widgets$w3 = gtable(mtcars[1:3,1:3], label="table", cont=nb)
# Save and restore actions
addHandlerClicked(save_btn, handler=function(...) {
values <<- lapply(widgets, svalue, index=TRUE)
state <<- lapply(widgets, "[")
})
addHandlerClicked(restore_btn, handler=function(...) {
if (!is.null(values)) {
for (nm in names(widgets)){
## screen for widgets without values
if (length(state[[nm]]))
widgets[[nm]] <- state[[nm]]
print(list(widgets[[nm]], values[[nm]]))
svalue(widgets[[nm]], index=TRUE) <- values[[nm]]
}
}
})
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
}
Is there a way to embed the function edit(dataframe) in gwindow?
example:
DataFrame <- data.frame(cbind(1,1:10)
edit(DataFrame)
Window <- gwindow()
I would like to embed edit(DataFrame) in Window.
Apostolos
The standard way to do this would be through a button click.
dfr <- data.frame(x = 1:10, y = runif(10))
win <- gwindow()
btnEdit <- gbutton(
"Edit",
container = win,
handler = function(h, ...) dfr <<- edit(dfr)
)
You can be even fancier and decide whether or not the data frame should be editable or just viewable.
win <- gwindow()
btnEdit <- gbutton(
"Edit",
container = win,
handler = function(h, ...)
{
if(svalue(chkReadonly)) View(dfr) else dfr <<- edit(dfr)
}
)
chkReadonly <- gcheckbox(
"Read-only",
FALSE,
container = win,
handler = function(h, ...)
{
svalue(btnEdit) <- if(svalue(h$obj)) "View" else "Edit"
}
)
Based upon your comment, what you want is even easier. Store the data frame in a gdf.
tbl <- gdf(dfr, container = win)