R Shiny:mainPanel 行为随输入而变化
RShiny : mainPanel behavior changing with input
每张图片上方都有一个操作按钮。但它的工作方式不同,具体取决于 input$n 的奇偶校验(在侧边栏面板中的数字输入中)。
如果 input$n 是奇数,单击按钮会更改标签,这正是我想要的。
否则,它没有。
请分别查找附件服务器和ui:
require(png)
require(shiny)
require(shinyjs)
########## PRE-PROCESSING
Nsub <- 5
Nimg <- 10
nvar <- 112*92
N <- Nsub * Nimg
#stocker noms fichiers et images
init <- function(){
listFiles <- list()
listDataMat <- list()
excluded <- list()
for( sub in 1:Nsub ){
listLabel <- c()
DataMat <- matrix(nrow=Nimg,ncol=nvar)
for( img in 1:Nimg ) {
fname <- paste("www/s",sub,"_",img,".png",sep="")
listLabel <- c(listLabel,fname)
d <- readPNG(fname)
DataMat[img,] <- matrix(d,ncol=nvar)
}
listFiles[[sub]] <- listLabel
listDataMat[[sub]] <- DataMat
excluded[[sub]] <- rep(FALSE,10)
}
list(listFiles,listDataMat,excluded)
}
lists <- init()
listFiles <- lists[[1]]
listDataMat <- lists[[2]]
excluded <- lists[[3]] #noms fichier exclus de database // %in%
remove(lists)
############ HELPER FUNC
#afficher images d'une classe
dispImgs <- function(variable,ind){
if(variable>=1){
DataMat <- listDataMat[[variable]]
}else{
DataMat <- listDataMat[["0"]]
}
result <- list()
outfile <- tempfile(fileext = ".png")
sample <- matrix(DataMat[ind,], nrow = 112, ncol = 92)
writePNG(sample, target = outfile)
im <- list(src = outfile,
contentType = "image/png",
alt = "Normalement, on devrait voir une photo",
width = 92,
height = 112
)
im
}
###########SERVER
server <- function(input,output,session){
excluded <- reactiveValues(ls = excluded)
# vals <- reactiveValues()
# vals$n_sample <- 10
# vals$n_rows <- *
# vals$last_row <- n_sample%%5
#
observeEvent(input$n,{
n_sample <- ifelse(input$n==0,nrow(listDataMat[["0"]]),nrow(listDataMat[[input$n]]))
n_rows <- round(n_sample/5)
last_row <- n_sample%%5
#creating event listener
lapply(
X = 1:n_sample,
FUN = function(i){
observeEvent(input[[paste0("out",i)]], {
excluded$ls[[input$n]][i] <- !excluded$ls[[input$n]][i]
updateActionButton(session, paste0("out",i),
label = ifelse(excluded$ls[[input$n]][i],"Inclure","Exclure"))
print(excluded$ls[[input$n]])
})
}
)
})
img_widget <- function(i) {
if(input$n==0){
column(2,
renderImage({
dispImgs(input$n,i)
},outputArgs = c(height="200px")
)
)
}else{
column(2,
actionButton(paste0("out",i), label = ifelse(excluded$ls[[input$n]][i],"Inclure","Exclure")),
renderImage({
dispImgs(input$n,i)
},
outputArgs = c(height="200px")
)
)
}
}
output$mainPanel <- renderUI({
mainPanel(
h2(paste("Les 10 photos de l'individu", input$n)),
# if(n_rows!=0){
# for(i in 1:n_rows){
# fluidRow(
# width=10,
# lapply(
# X = 1+5*(i-1):5*i,
# FUN = img_widget
# )
# )
# }
# }
# if(last_row!=0){
# fluidRow(
# width=10,
# lapply(
# X = 1+5*(n_rows-1):5*(n_rows-1)+last_row,
# FUN = img_widget
# )
# )
# }
fluidRow(
width=10,
lapply(
X = 1:5,
FUN = img_widget
)
),
fluidRow(
width=10,
lapply(
X = 6:10,
FUN = img_widget
)
)
)
})
}
require(png)
require(shiny)
######### HELPER FUNC
########## UI
ui <- fluidPage(
# Titre
headerPanel("Banque de photos pour reconnaissance faciale"),
sidebarLayout(
sidebarPanel(
numericInput('n', "Numéro de l'individu à afficher", 1, min = 0, max = 40, step = 1)
),
uiOutput("mainPanel")
)
)
为了重现问题,您需要一个包含名为 's1_2.png' 的图片的文件夹 'www',其中 1 是 class,2 是图片索引。
每个 class (S[1-5]_[1-5].png) 只能定义 5 张图片。因此自然会出现一个小的显示问题。
编辑:忘了说图片需要灰度。
查看 print(excluded$ls[[input$n]])
输出,似乎每次触发 input$n
时,它都会增加触发任何 [=14= 时将启动的 updateActionButton()
的数量].
因此,例如,触发 2 次 input$n
然后单击任何 input$outN
按钮将启动 updateActionButton
两次而不是一次。所以它首先排除但然后重新包含您的样本。当 input$n
被触发奇数次时,它最终以排除样本结束,所以这就是它 似乎 起作用的原因。
不确定为什么会这样,但肯定是因为有两个嵌套 observeEvent
。可能已经观察到类似的行为(双关语)already.
如果您不嵌套这两个 observeEvent
,它会按预期工作:
n_sample <- nrow(listDataMat[[1]])
observeEvent(input$n,{
n_sample <- ifelse(input$n==0,nrow(listDataMat[["0"]]),nrow(listDataMat[[input$n]]))
n_rows <- round(n_sample/5)
last_row <- n_sample%%5
})
#creating event listener
lapply(
X = 1:n_sample,
FUN = function(i){
observeEvent(input[[paste0("out",i)]], {
excluded$ls[[input$n]][i] <- !excluded$ls[[input$n]][i]
updateActionButton(session, paste0("out",i),
label = ifelse(excluded$ls[[input$n]][i],"Inclure","Exclure"))
print(excluded$ls[[input$n]])
})
}
)
但是您需要在第一个 observeEvent
之外定义 n_sample
变量,以便 lapply
函数可以使用它。我通过“静态”定义它来简化,但您需要一些 reactiveValue
以便在触发第一个 observeEvent
.
时更新它
每张图片上方都有一个操作按钮。但它的工作方式不同,具体取决于 input$n 的奇偶校验(在侧边栏面板中的数字输入中)。 如果 input$n 是奇数,单击按钮会更改标签,这正是我想要的。 否则,它没有。
请分别查找附件服务器和ui:
require(png)
require(shiny)
require(shinyjs)
########## PRE-PROCESSING
Nsub <- 5
Nimg <- 10
nvar <- 112*92
N <- Nsub * Nimg
#stocker noms fichiers et images
init <- function(){
listFiles <- list()
listDataMat <- list()
excluded <- list()
for( sub in 1:Nsub ){
listLabel <- c()
DataMat <- matrix(nrow=Nimg,ncol=nvar)
for( img in 1:Nimg ) {
fname <- paste("www/s",sub,"_",img,".png",sep="")
listLabel <- c(listLabel,fname)
d <- readPNG(fname)
DataMat[img,] <- matrix(d,ncol=nvar)
}
listFiles[[sub]] <- listLabel
listDataMat[[sub]] <- DataMat
excluded[[sub]] <- rep(FALSE,10)
}
list(listFiles,listDataMat,excluded)
}
lists <- init()
listFiles <- lists[[1]]
listDataMat <- lists[[2]]
excluded <- lists[[3]] #noms fichier exclus de database // %in%
remove(lists)
############ HELPER FUNC
#afficher images d'une classe
dispImgs <- function(variable,ind){
if(variable>=1){
DataMat <- listDataMat[[variable]]
}else{
DataMat <- listDataMat[["0"]]
}
result <- list()
outfile <- tempfile(fileext = ".png")
sample <- matrix(DataMat[ind,], nrow = 112, ncol = 92)
writePNG(sample, target = outfile)
im <- list(src = outfile,
contentType = "image/png",
alt = "Normalement, on devrait voir une photo",
width = 92,
height = 112
)
im
}
###########SERVER
server <- function(input,output,session){
excluded <- reactiveValues(ls = excluded)
# vals <- reactiveValues()
# vals$n_sample <- 10
# vals$n_rows <- *
# vals$last_row <- n_sample%%5
#
observeEvent(input$n,{
n_sample <- ifelse(input$n==0,nrow(listDataMat[["0"]]),nrow(listDataMat[[input$n]]))
n_rows <- round(n_sample/5)
last_row <- n_sample%%5
#creating event listener
lapply(
X = 1:n_sample,
FUN = function(i){
observeEvent(input[[paste0("out",i)]], {
excluded$ls[[input$n]][i] <- !excluded$ls[[input$n]][i]
updateActionButton(session, paste0("out",i),
label = ifelse(excluded$ls[[input$n]][i],"Inclure","Exclure"))
print(excluded$ls[[input$n]])
})
}
)
})
img_widget <- function(i) {
if(input$n==0){
column(2,
renderImage({
dispImgs(input$n,i)
},outputArgs = c(height="200px")
)
)
}else{
column(2,
actionButton(paste0("out",i), label = ifelse(excluded$ls[[input$n]][i],"Inclure","Exclure")),
renderImage({
dispImgs(input$n,i)
},
outputArgs = c(height="200px")
)
)
}
}
output$mainPanel <- renderUI({
mainPanel(
h2(paste("Les 10 photos de l'individu", input$n)),
# if(n_rows!=0){
# for(i in 1:n_rows){
# fluidRow(
# width=10,
# lapply(
# X = 1+5*(i-1):5*i,
# FUN = img_widget
# )
# )
# }
# }
# if(last_row!=0){
# fluidRow(
# width=10,
# lapply(
# X = 1+5*(n_rows-1):5*(n_rows-1)+last_row,
# FUN = img_widget
# )
# )
# }
fluidRow(
width=10,
lapply(
X = 1:5,
FUN = img_widget
)
),
fluidRow(
width=10,
lapply(
X = 6:10,
FUN = img_widget
)
)
)
})
}
require(png)
require(shiny)
######### HELPER FUNC
########## UI
ui <- fluidPage(
# Titre
headerPanel("Banque de photos pour reconnaissance faciale"),
sidebarLayout(
sidebarPanel(
numericInput('n', "Numéro de l'individu à afficher", 1, min = 0, max = 40, step = 1)
),
uiOutput("mainPanel")
)
)
为了重现问题,您需要一个包含名为 's1_2.png' 的图片的文件夹 'www',其中 1 是 class,2 是图片索引。 每个 class (S[1-5]_[1-5].png) 只能定义 5 张图片。因此自然会出现一个小的显示问题。
编辑:忘了说图片需要灰度。
查看 print(excluded$ls[[input$n]])
输出,似乎每次触发 input$n
时,它都会增加触发任何 [=14= 时将启动的 updateActionButton()
的数量].
因此,例如,触发 2 次 input$n
然后单击任何 input$outN
按钮将启动 updateActionButton
两次而不是一次。所以它首先排除但然后重新包含您的样本。当 input$n
被触发奇数次时,它最终以排除样本结束,所以这就是它 似乎 起作用的原因。
不确定为什么会这样,但肯定是因为有两个嵌套 observeEvent
。可能已经观察到类似的行为(双关语)already.
如果您不嵌套这两个 observeEvent
,它会按预期工作:
n_sample <- nrow(listDataMat[[1]])
observeEvent(input$n,{
n_sample <- ifelse(input$n==0,nrow(listDataMat[["0"]]),nrow(listDataMat[[input$n]]))
n_rows <- round(n_sample/5)
last_row <- n_sample%%5
})
#creating event listener
lapply(
X = 1:n_sample,
FUN = function(i){
observeEvent(input[[paste0("out",i)]], {
excluded$ls[[input$n]][i] <- !excluded$ls[[input$n]][i]
updateActionButton(session, paste0("out",i),
label = ifelse(excluded$ls[[input$n]][i],"Inclure","Exclure"))
print(excluded$ls[[input$n]])
})
}
)
但是您需要在第一个 observeEvent
之外定义 n_sample
变量,以便 lapply
函数可以使用它。我通过“静态”定义它来简化,但您需要一些 reactiveValue
以便在触发第一个 observeEvent
.