I am creating a gbutton in gWidgets2 which will toggle between "go" and "stop" when it will be clicked.
I am following this example: toggling a group of icons in gWidgets
My Code:
library(gWidgets2)
library(gWidgets2RGtk2)
options(guiToolkit="RGtk2")
w= gwindow()
g1 <- ggroup(horizontal=TRUE, cont=w)
icon <- gbutton('go', container = g1)
state <- FALSE # a global
changeState <- function(h,...) {
if(state) {
svalue(icon) <- "go"
} else {
svalue(icon) <- "stop"
}
state <<- !state
}
addHandlerClicked(icon, handler=changeState)
It creates a button and toggle between "go" and "stop" when it is clicked. But the problem is I have to click two times to toggle. I want it should toggle between "go" and "stop" on one click.
You can use blockHandlers() and unblockHandlers() functions to avoid this issue.
w= gwindow()
g1 <- ggroup(horizontal=FALSE, cont=w)
icon <- gbutton("go", container = g1)
#icon <- gimage(reject,cont=g1)
state <- FALSE # a global
addHandlerClicked(icon, function(h,...) {
#
if(!state) {
blockHandlers(icon)
svalue(icon) <- "stop"
unblockHandlers(icon)
} else {
blockHandlers(icon)
svalue(icon) <- "go"
unblockHandlers(icon)
}
state <<- !state
})
I tried this and it works for me.
Related
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
} )
}
I am trying to write a Shiny app for a class I'm teaching that draws a random sample from a dataset and computes summary statistics. Whenever I press the reset button on the UI, a new subset should be sampled. Here is my code so far:
shinyServer(function(input, output) {
# Output for Ch. 1 Problems: Central Tendency
# Prepare data
observeEvent(input$Ch1.Prob.CT.reset, {
Ch1.Prob.CT.n <- sample(8:12, 1)
Ch1.Prob.CT.obs <- sample(1:nrow(cars), Ch1.Prob.CT.n)
})
data <- eventReactive(input$Ch1.Prob.CT.reset, {
cars[Ch1.Prob.CT.obs, 'dist', drop=F]
})
# Outputs
output$Ch1.Prob.CT.Data <- renderDataTable({
data()
})
output$Ch1.Prob.CT.Mean.out <- renderUI({
if (is.na(input$Ch1.Prob.CT.Mean.in)) { # Error checking
p("No answer provided")
} else if (round(input$Ch1.Prob.CT.Mean.in, digits = 4) == round(mean(Ch1.Prob.CT.data[,1]), digits = 4)) {
p("Correct", style = "color:green")
} else {
p("Incorrect", style = "color:red")
}
})
})
The problem is that the sample is not random; it is always the same, every time. Even when I press the reset button, the sample is exactly the same as the one before.
Why is Shiny not randomizing? And how can I make it randomize again?
Add a line such as
set.seed(as.integer(Sys.time()))
before you need random numbers
Such code:
observeEvent(input$xxx, {
x <- ...
})
f <- eventReactive(input$xxx, {
[do something with x]
})
does not work.
You can simply remove the observer and do:
f <- eventReactive(input$xxx, {
x <- ...
[do something with x]
})
If you want to use a variable subject to modifications inside an observer, you have to use a reactive list, like this :
values <- reactiveValues()
values$x <- [initial value of x]
observeEvent(input$xxx, {
values$x <- ...
})
(In addition, don't use some dots (.) in the names of the shiny elements.)
Adapting an example I can toggle the display of an icon like this:
reject <- "D:/Pictures/web/close32.png"
accept <- "D:/Pictures/web/open32.png"
w= gwindow()
g1 <- ggroup(horizontal=TRUE, cont=w)
icon <- gimage(reject,cont=g1)
state <- FALSE # a global
changeState <- function(h,...) {
if(state) {
svalue(icon) <- reject
} else {
svalue(icon) <- accept
}
state <<- !state
}
addHandlerClicked(icon, handler=changeState)
However, I would like to get this to work with a group of icons
example 3x3 icon grouping http://cran.r-project.org/web/packages/gWidgets/vignettes/gWidgets.pdf
so that each icon can be toggled and I can retrieve the state of the icons as a vector. The purpose is to create a graphical selector for picking pairs of observations to perform analysis on. Here is my attempt. It displays correctly, but does not respond to clicks to change the state. I recognize that I am confusing how the handler and action parameters act together and would appreciate any clarifications and fixes for this code.
reject <- "D:/Pictures/web/close32.png"
accept <- "D:/Pictures/web/open32.png"
w= gwindow()
g1 <- ggroup(horizontal=TRUE, cont=w)
lyt <- glayout(cont=g1, spacing=10)
icon <- rep(reject,times=9)
state <- rep(FALSE, times=9)
changeState <- function(h,...) {
if(state[index]) {
svalue(icon[index]) <- reject
} else {
svalue(icon[index]) <- accept
}
state[index] <<- !state[index]
}
for(i in 1:3){
for(j in 1:3){
ind <- (i-1) * 3 +j
lyt[i,j] <- gimage(icon[ind], cont=lyt)
addHandlerClicked(lyt[i,j], handler=changeState, action= index <-ind)
}
}
1c: http://i.stack.imgur.com/4kbwK.png
The index value must be retrieved from h$action in your handler (index <- h$action). As well, this bit action=index <- ind need only be action=ind.
In various programs you can often activate a button using an alt+c key binding, if for example the button in question is Close. How is it possible to do this in gWidgets2? Take this example:
w <- gwindow("Buttons")
g <- ggroup(cont=w, horizontal=FALSE)
## various buttons
## without icon
b2 <- gbutton("ouvrir", cont=g)
## with a handler
b4 <- gbutton("click me", cont=g, handler=function(h,...) {
if(svalue(b2) == "open")
svalue(b2) <- "ouvrir"
else
svalue(b2) <- "open"
})
How can I have the c underlined in click me, and the handler of the b4 button activated when the user activates alt+c?
How is it possible to trigger the handler of a button in gWidgets2? Take this example:
w <- gwindow("Buttons", visible=FALSE)
g <- ggroup(cont=w, horizontal=FALSE)
## various buttons
## without icon
b2 <- gbutton("ouvrir", cont=g)
## with a handler
b4 <- gbutton("click me", cont=g, handler=function(h,...) {
if(svalue(b2) == "open")
svalue(b2) <- "ouvrir"
else
svalue(b2) <- "open"
})
visible(w) <- TRUE
I can trigger the handler of b4 by using the mouse and "physically" clicking on the button. But how can I achieve this via some R code? I am hoping for something like activateHandler(b4) or similar.
As per the suggestions in the comments, I can either via b4$invoke_change_handler(). Or by redefining the handler as a separate function:
w <- gwindow("Buttons", visible=FALSE)
g <- ggroup(cont=w, horizontal=FALSE)
## various buttons
## without icon
h2 <- function(h,...) {
if(svalue(b2) == "open")
svalue(b2) <- "ouvrir"
else
svalue(b2) <- "open"
}
b2 <- gbutton("ouvrir", cont=g)
## with a handler
b4 <- gbutton("click me", cont=g, handler=h2)
visible(w) <- TRUE
and then calling that: h2().