r - 在while循环中使用R闪亮服务器控制循环执行
问题描述
我正在尝试创建一个简单的应用程序,它将循环执行以下操作: 0. 等待开始按钮 1. 系统调用以创建屏幕截图并将其保存到磁盘 2. 将屏幕截图从磁盘渲染到闪亮的输出 3.打印状态“filename - ok” 4. Sys.sleep 例如 5 秒 5. 检查停止按钮是否未激活 - 转到 1。
代码中的这个想法:
ui <- fluidPage(
titlePanel("My App"),
sidebarLayout(
sidebarPanel(
radioButtons("control", h3("Start/Stop switch"),
choices = list("Start" = TRUE,
"Stop" = FALSE
),selected = TRUE),
actionButton("go", label = "Go!")
),
mainPanel(
textOutput("status"),
imageOutput("image")
)
)
)
server <- function(input, output) {
actionflag <- eventReactive(input$go,{input$control})
while (actionflag()==TRUE) {
fname<-gsub("[[:punct:] ]", "", Sys.time())
system(paste0("screencapture -t jpg -x ~/Documents/Screens/", fname,".jpg"))
output$status <- renderText({paste(fname,"screen captured")})
output$image <- renderImage({
list(src = paste0("~/Documents/Screens/",fname,".jpg"),
alt = "Image",
width = 400,
height = 300)
}, deleteFile = FALSE)
Sys.sleep(5)
}
}
但它不是这样工作的。正式地我得到这个错误: .getReactiveEnvironment()$currentContext() 中的错误:没有活动的反应上下文不允许操作。(你试图做一些只能从反应式表达式或观察者内部完成的事情。)
此外,即使没有控制按钮(while(1==1){execute code}),我也无法在闪亮的服务器中使用 while 循环来不断更改输出。我猜这个'while'实现是完全错误的,所以任何建议都值得赞赏
解决方案
这是一个带有 2 个按钮(开始和停止)的闪亮应用程序。当按下“开始”时,每 5 秒截取一次屏幕截图并在 UI 中呈现。“循环”通过观察我们可以在此示例中的服务器中创建的名为“rv$loop”的反应值来发生。'go' 按钮总是使 'rv$loop' 为 1,'stop' 按钮总是使 'rv$loop' -100。如果 'rv$loop' > 0,则代码将通过在重新触发开始的观察者的末尾始终将 1 添加到 'rv$loop' 来执行并连续运行。
此外,shinyjs包功能“延迟”允许在执行一行代码之前进行时间延迟,而不会使整个 R 会话进入睡眠状态,从而允许将新的屏幕截图加载到浏览器中。要使用 shinyjs,需要在 UI 代码中的某处删除“useShinyJs()”行。
通常闪亮的应用程序只能访问其应用程序目录中包含的某些文件夹,它知道要查看并且默认情况下与应用程序一起启动,例如静态图像/徽标/等的“www”文件夹。要将文件夹添加为资源文件夹,您需要使用“ addResourePath ”使“~/Documents/Screens”在应用程序启动时可用。
此示例应用程序只有在您的机器上有一个“~/Documents/Screens”目录时才能工作。如果需要,取消注释前几行以创建此目录。
library(shiny)
library(shinyjs)
#make sure this directory exists
#uncomment and run if there is no 'Screens' folder in your 'Documents'
# if(!file.exists("~/Documents/Screens")){
# dir.create("~/Documents/Screens")
# }
ui <- fluidPage(
useShinyjs(), #make sure to drop this useShinyJs line somewhere in UI
actionButton("go", label = "Go!"),
actionButton("stop", label = "Stop!"),
textOutput('status'),
uiOutput("image")
)
server <- function(input, output, session) {
#allow shiny app to access files in this non-shiny app directory folder
addResourcePath("screen", "~/Documents/Screens")
#this reactive value rv$loop will serve as our loop starter/stopper
rv <- reactiveValues(loop = 0)
#if input go is clicked the loop is started
#because the observe event only continues if rv$loop is > 0
observeEvent(input$go,{
rv$loop <- 1
})
#if input stop is clicked loop is stopped
#because this makes rv$loop -100, which is < 0
#so observe event is not triggered again for the screenshot loop
observeEvent(input$stop,{
rv$loop <- -100
})
#observe changes in the rv$loop variable
#only do anything if the rv$loop value is greater than 0
#if it is triggered the last line adds 1 to rv$loop
#which re-validates the observeEvent to trigger it again
#it only stops if input$stop is pushed to make rv$loop -100
observeEvent(rv$loop, {
if(rv$loop > 0){
#add the name of file to a reactive value to access inside/outside of this observe event
rv$name <- gsub("[[:punct:] ]", "", Sys.time())
system(paste0("screencapture -t jpg -x ~/Documents/Screens/", rv$name,".jpg"))
#use shinyjs function 'delay' to wait to add 1
#or Sys.sleep put everything to sleep and the app
#would not load the imaged because it was asleep an
#did not have enough time.
shinyjs::delay(5000, rv$loop <- rv$loop + 1)
}
})
output$status <- renderText({paste(rv$name,"screen captured")})
output$image <- renderUI({
img(src = paste0('screen/', rv$name, '.jpg'))
})
}
shinyApp(ui, server)
PS - 我从来不知道你可以这样截图,我觉得它很整洁。
推荐阅读
- firebase-cloud-messaging - 同一域上的多个 TWA 上的 FCM 推送通知
- google-cloud-dataflow - 如何限制使用 FileIO 写入的每个文件的行数
- database - cloud spanner IAM权限,限制对数据库的访问
- javascript - 在 React 中通过 onClick 更改元素的 className 会触发重新渲染,但条件 className 构造不会?
- flutter - 如何将 suffixIcon 对齐到多行 TextField 的顶部?
- javascript - 循环基础
- r - R zeroinfl 模型错误 - 这是什么意思?
- sql - 如何在 SQL 语句中使用 GROUP BY 和 JOIN?
- javascript - 如何在不使用 POST 请求的情况下访问服务器端 Node.js + Expressjs 中静态文件中的变量/方法?
- sass - brew 名称中的 /(斜杠)是否有特殊含义?或者它只是作为字符串的斜线?