I wish to insert a 'loading' GIF image to my tcltk window but just can't get my head around it. Following is a reproducible example:-
backg <- 'white'
pdlg <- tktoplevel(background=backg)
tcl('wm', 'geometry', pdlg, '500x100+450+350')
tilg <- 'Package installation in progress'
tkwm.title(pdlg, tilg)
fn <- tkfont.create(family = 'helvetica', size = 12)
nwlabel <- " The requisite packages are being installed. This may take several \nminutes... \n"
tllab <- tklabel(pdlg, text = nwlabel, font = fn, pady = 0, background=backg)
clickEv <- tclVar(0)
OK.but <- tkbutton(pdlg, text=' Stop ', command=function() tclvalue(clickEv) <- 1, font=fn, background='grey', pady=0)
tkgrid(tllab, columnspan=1)
tkgrid(OK.but, row=3)
tkbind(pdlg, "<Destroy>", function() tclvalue(done) <- 2)
tkfocus(pdlg)
#This allows me to insert a GIF image but the animation is lost. Also it would be convenient if the output can be obtained using 'tkgrid' instead of 'tkpack'
pdlg2 <- tktoplevel(background='white')
loading <- tclVar()
tcl('image', 'create', 'photo', loading,
file='file path to GIF file')
trial <- tklabel(pdlg2, image=loading)
tkpack(trial)
An example GIF file can be downloaded from here -http://www.dlfpramericalife.com/library/images/final_loading_big.gif
Ideally, the GIF image should be placed above the 'Stop' button but below the text. Many thanks for your help!
In Tcl/Tk, it's quite easy.
set img [image create photo -file nameofthefile.gif]
label .l -image $img
I don't know R, but taking your code as a guide, I imagine something like this, but please check it!
img <- tkimage.create('photo', file='nameofthefile.gif')
imglab <- tklabel(pdlg, image = img)
... then you grid/pack/place it wherever you want. Please note that this don't work with animated gifs and I think animation must be hand-handler, using a timer which updates periodically the image content, but I never did it, nor I know how to do. You may check the Tcl/Tk wiki for more help.
Related
I have a large dataframe that I presented as a formattable object. When the object renders in the R Studio viewer, I have a scrollbar to move up and down. But when I export the image it does not export the whole table, just a part of it. How can I export the whole table as an image?
Here is my code for the formattable object:
formattable(por.pais,align =c("c","c","c","c"),
list('Equipo' = formatter("span", style = ~ style(color = "grey",font.weight ="bold")), 'Eficiencia'= color_tile(customRed, customGreen)))
And here is how R is exporting the image:
formattable object
Yes, in Viewer, Export, you can get a maximum of 1820 pixels wide and 796 pixels high. If you increase the pixels and click update preview this will help with medium sized tables that are within this size, but does not help if your table is bigger (like mine).
Ok so I found this code and it works to perfection:
First, install the formattable, htmltools and webshot packages:
install.packages("htmltools")
install.packages("webshot")
install.packages("formattable")
Now load them:
#Load the following libraries:
library("htmltools")
library("webshot")
Run the following function:
export_formattable <- function(f, file, width = "100%", height = NULL,
background = "white", delay = 0.2)
{
w <- as.htmlwidget(f, width = width, height = height)
path <- html_print(w, background = background, viewer = NULL)
url <- paste0("file:///", gsub("\\\\", "/", normalizePath(path)))
webshot(url,
file = file,
selector = ".formattable_widget",
delay = delay)
}
Now, create a formattable object:
tb <- formattable(dataframe)
Fianlly, save your table as an image:
export_formattable(tb,"my_table.png")
Note: You can also use the .jpg extension.
I tried sample codes for visExport() and is able to add a "Export as PNG" button to a Shiny webpage. But this would need user interaction to press the button to export the network to a PNG image file.
I have over hundred of networks and would like to export them each to a PNG file. And some of these would need regular updating. So it would be logistically nice to be able to export all them to PNG files without a user pressing the "Export as PNG" button for each of the network.
So is it possible to programmatically export a list of networks one by one to PNG? This would be just like for visSave() to export the HTML for each network one by one.
In reference to other post, here is working code making use of the webshot package.
library(visNetwork)
library(tidyverse)
library(webshot)
# create network data
nodes = data.frame(id = numeric(),label=character(),set = numeric(),stringsAsFactors = F)
edges = data.frame(from = numeric(),to = numeric(),set = numeric(),stringsAsFactors = F)
for (i in 1:10){
tempNodes <- data.frame(id = 1:15, label = paste("Label", 1:15), set = i)
tempEdges <- data.frame(from = trunc(runif(15)*(15-1))+1,
to = trunc(runif(15)*(15-1))+1, set = i)
nodes = rbind(nodes,tempNodes)
edges = rbind(edges,tempEdges)
}
# loop through each set to export to PNG
for (i in 1:max(nodes$set)){
subNodes = nodes[nodes$set==i,]
subEdges = edges[edges$set==i,]
network = visNetwork(subNodes, subEdges, width="100vw",height = "100vh") %>%
visLayout(randomSeed=1,improvedLayout=TRUE) %>%
visGroups(groupname = "actorImported",shape="circle") %>%
visEdges(smooth=FALSE) %>%
visPhysics(solver = "barnesHut")
fname = paste0("network",sprintf("%03d",i),".html")
visSave(network,fname)
webshot(fname,delay=0.5,zoom=2,file=paste0("network",sprintf("%03d",i),".png"),
vwidth=900,vheight=900)
}
The short answer must be "Yes", but since you've not given us any sample code, it's impossible to give you a tested solution. But you say you have a hundred networks. Let's assume there in a vector networks. (A list would work as well with minor changes to the sample code below.) You can export one graph using a Shiny button. So you must have code to create a single network image. Suppose that's in a function createImageForNetwork(x), where x is a network. You'll also need a function to create an output file name for each image. Suppose that's called getFilename(x). Then something like the untested code below will do what you want:
exportNetworkImage <- function(x) {
png(getFilename(x))
createImageForNetwork(x)
dev.off()
}
lapply(1:length(networks), function(x) exportNetworkImage(networks[x]))
If you want to do that with a single button click in your Shiny app, then just put that code inside the button's observeEvent handler.
I am working with a function that outputs an svg object. As I see the SVG object is essentially a string of characters.
I was wondering how to
1) plot the svg output from the function
2) save this svg object to disk under an svg extension? I tried ggsave but just resulted in an error.
I am fairly new to svg handling, so would appreciate any inputs.
Thanks!
1) I tried that for a package I was developing and it was not straightforward. In the end, I needed two libraries: rsvg and grImport2. Here is the code I used:
tfile <- tempfile(fileext = ".svg")
tfile2 <- tempfile(fileext = ".png")
cat(svg_code, file=tfile)
if (requireNamespace("rsvg", quietly = TRUE) && requireNamespace("grImport2", quietly = TRUE)) {
rsvg::rsvg_svg(svg = tfile, tfile2)
p <- grImport2::readPicture(tfile2)
grImport2::grid.picture(p)
} else {
if (systemShow == FALSE && outFile == ''){
warning("The figure cannot be rendered in the plot window. Please, use the arguments outFile and/or systemShow.")
}
}
if (systemShow){
utils::browseURL(tfile)
}
The first conditional is in case the system does not allow the installation of either package. As you can see, you first need to write the svg code (svg_code) to a file, in this case temporary (tfile). Then, rsvg_svg writes a temporary png file (tfile2). Finally, grImport2::readPicture and grImport2::grid.picture show the converted file in the plot window. I also left the part where the user can set a boolean variable (systemShow) and the package will attempt to open the file on the default system svg viewer.
2) That one is much easier. You just need to write the code to a file as text, like cat(svg_code, file='path_to_file.svg').
I'm trying to add an image to a datatable in R form the DT package. I fount this question: How to embed an image in a cell a table using DT, R and Shiny and it works for the image that's online. But when I tried to add a image that i have locally (created with R) it just doesn't come up. This is an example of my problem:
x = rnorm(1000)
png(paste0("Graficas/test.png"))
Plot = plot(x, type = "l")
dev.off()
camino = '<img src="Graficas/test.png" height="30"></img>'
data = data.frame(0.5,camino)
datatable(data, escape = FALSE)
the output is
and I can't understand why its happening
This is one way to do it (by embedding base64 encoded images and using that for the src).
First we'll make a small helper:
img_uri <- function(x) { sprintf('<img src="%s"/>', knitr::image_uri(x)) }
That will let us make a data uri. We're slurping up the whole file and converting it to base64 then doing a bit more formatting before sticking the entire blob into the src attribute.
This is what a 1x1 pixel PNG looks like encoded that way:
<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=\"/>
So, we just do the same with the one you created:
x = rnorm(1000)
png(paste0("test.png"))
Plot = plot(x, type = "l")
dev.off()
camino = img_uri("test.png")
data = data.frame(0.5 ,camino)
DT::datatable(data, escape = FALSE)
Yours is having an issue b/c it's not "URI" and it has no way of pulling from the local system. It might work in a browser context with a file://… URL.
I am trying to create a GUI using gWidgetsRGtk2 for a program that I have written in R. My GUI has a gedit() text box in which the user can type a file path for the input data file to be put into the program. It also has a 'browse' button, which, when clicked, opens up a gfile() box so that they can browse for the file that they want. What I am having trouble with is updating the value in my gedit() box, after the user has selected their file using the 'browse' button. The code below may make this clearer:
dir <- getwd()
sfilepath <- paste0(dir,"/")
win = gwindow("Set Parameters:",width=400,height=550)
nb = gnotebook(cont=win)
tab2 <- glayout(cont=nb, label = "Advanced Settings")
tab1 <- glayout(cont=nb, label = "Basic Settings")
tab1[2,2] <- glabel("BD:",cont=tab1)
tab1[2,4:5] <- gedit(1,cont=tab1)
addhandlerkeystroke(tab1[2,4],handler=function(h,...){BD <<- as.numeric(svalue(h$obj))})
tab1[3,2:5] <- gseparator(cont=tab1)
tab1[4,2:5] <- glabel("File path:",cont=tab1)
tab1[5,2:4] <- gedit(paste0(dir,"/"),cont=tab1)
tab1[5,5] <- gbutton(text="Browse", handler=function(h,...){ gfile("Select a file",type="open", filter = list("text files" = list(patterns = c("*.csv","*.txt")), "R files" =list(patterns = c("*.R","*.Rdata"))), handler = function(h,...){ sfilepath <<- h$file},cont=TRUE)},cont=tab1)
addhandlermousemotion(tab1[5,2],handler=function(h,...){svalue(h$obj) <- sfilepath})
So far I have tried using addhandlermousemotion, as in the code above, so the text in the gedit() box is only updated when you move the mouse over the box itself. However, I would prefer it if the text in the box updated instantly.
I have also tried using addhandleridle(), with an interval of 1 second, so that the text in the box will be automatically updated every 1 second. This worked. However, it made it impossible to type in the box properly, because the text box was being updated with the old 'sfilepath' before it had saved the new 'sfilepath' that was being typed in.
I am a beginner at making at GUIs (I have written a program for work, but it needs to be used by someone else once I leave, so decided last Friday that I should figure out how to make it into a GUI). So any help that anyone can offer would be greatly appreciated.
Here is the pattern you want (passing a handler to gfilebrowse):
w <- gwindow("test")
g <- ggroup(cont=w, horizontal=FALSE)
file_upload <- gfilebrowse(cont=g, handler=function(h,...) {
svalue(e) <- svalue(h$obj)
})
e <- gedit("", cont=g)