Non editable box with tcl tk and R - r

I am looking for some way to forbid users to change value in a text box with tcltk and R.
Here is what I have done : I want to forbid users to change the value in the first box.
library(tcltk)
tt <- tktoplevel()
v <- tclVar("32 200 700")
entry.1 <-tkentry(tt, width = "50", textvariable = v)
tkbind(entry.1, "<Key>", function()tkfocus(entry.2))
tkgrid(entry.1, row=1, column=0)
v2 <- tclVar("")
entry.2 <-tkentry(tt, width = "50", textvariable = v2)
tkgrid(entry.2, row=2, column=0)
It seems to work but key's native action is done before bound action.
How can I solve this problem ?
I don't want to use tklabel because it can't bring borders to the text.

This is plain Tcl, not R syntax, but you want to set the widget's state to readonly. That will forbid the user from modifying the value, but it still respects changes to the text variable. You don't need to bind anything, the user cannot focus on the widget.
set value 0
entry .e -textvariable value -state readonly
button .b -text incr -command {incr value}
pack .e .b

Related

tk2combobox: how to control response to up/down arrow keys

I've got a UI in R using tk2combobox.
If the control has focus, and I hit the "down-arrow" key, it expands the list, rather than changing the selection.
It doesn't actually change the selection until I arrow down and hit "enter" or click with the mouse.
Is there any way I can get it to change the selection immediately with the arrow key?
This is how you do it in Tcl. I could not get the very first
key-down to work, as somehow the interactions in bindings caused
the second key-press to disappear.
package require Tk
proc ::lbarrowhandler { w } {
set currselidx [$w curselection]
regsub {\.popdown\.f\.l$} $w {} cb
$cb current $currselidx
return -code ok
}
set ::x cc
ttk::combobox .c -values {aa bb cc dd ee ff} -textvariable ::x
pack .c
bind ComboboxListbox <<ListboxSelect>> +[list ::lbarrowhandler %W]
Edit:
Another possibility is to use the ttk::spinbox with the -values option.
I don't know your exact use case, but this will give the user a limited
selection of values. The disadvantage here is that the complete list
is not visible.
set ::x cc
ttk::spinbox .sp -values {aa bb cc dd ee ff} -state readonly \
-wrap true -textvariable ::x
pack .sp
The -state readonly prevent the user from typing anything in, and the
-wrap option will have the arrow controls wrap from end to beginning and
vice-versa.
References: http://www.tcl-lang.org/man/tcl/TkCmd/ttk_spinbox.htm

Empty string returned while trying to retrieve the text contents of an element of QListView

I am trying to automate a PyQt based application that uses a QListView in icon mode using Squish
Inorder to select a specific item in the view, i need to first identify the text of the item. I am using the below code to do the same
targetList = waitForObject("{name='someListView' type='QListView'}")
object.children(targetList)[11].model().data(object.children(targetList)[11]).toString()
Here object.children(targetList)[11] is of type QModelIndex
But the above code always returns an empty string.
Is there any other way to retrieve the text data
I would rather use QListView API only. So, in case of valid targetList object, i.e. it's found by waitForObject function, I would write:
targetList = waitForObject("{name='someListView' type='QListView'}")
model = targetList.model()
col = targetList.modelColumn
idx = model.index(11, col)
itemString = idx.data().toString()
Here is an example:
def main():
# Use itemviews example included in Squish:
startApplication("itemviews")
# Configure QListView to use IconMode as
# mentioned by original poster:
obj = waitForObject("{occurrence='2' type='QListView' unnamed='1' visible='1'}")
obj.setViewMode(QListView.IconMode)
# Get desired item via object.children();
# this yields a "wrapped" QModelIndex which
# features a property "text" which contains
# the desired text:
it = object.children(obj)[4]
test.log("item text: %s" % it.text)

R: Running computation while waiting for user input

do you see a way to run a computation in R while waiting for a user input?
I'm writing a script that makes differents types of plots which are defined by user input, but in first lot of data has to be loaded and processed. But in fact, user could start defining what he wants already while the processing is running - that's what I would like to do!
I think package Rdsn might provide the functionality that I need, but I was not able to figure out how.
Thanks!
You didn't give me much context, nor reproducible code, so I will just provide a simple example. I am not familiar with the Rdsn package, so I will use provide a solution I know.
# create a function to prompt the user for some input
readstuff = function(){
stuff = readline(prompt = "Enter some stuff: ")
# Here is where you set the condition for the parameter
# Let's say you want it to be an integer
stuff = as.integer(stuff)
if(is.na(stuff)){
return(readstuff())
} else {
return(stuff)
}
}
parameter = readstuff()
print(parameter)
print(parameter + 10)
The key here is to "source" the script instead of "running" it. You can find the "source" button on the top right of RStudio. You can also use source(yourscript) to source it.
So for every parameter you want to prompt the user for input, just call readstuff(). You can also tweak it a little to make it more general. For example:
# create a function to prompt the user for some input
readstuff = function(promptMessage = "stuff", class = "integer"){
stuff = readline(prompt = paste("Enter the", promptMessage, ": "))
# Here is where you set the condition for the parameter
# Let's say you want it to be an integer
stuff = as(stuff, class)
if(is.na(stuff)){
return(readstuff(promptMessage, class))
} else {
return(stuff)
}
}
plotColor = readstuff("plot color", "character")
size = readstuff("size parameter")
xvarName = readstuff("x axis name", "character")
df = data.frame(x = 1:100, y = 1:100)
library(ggplot2)
p = ggplot(df, aes(x = x, y = y, size = size, color = plotColor)) +
labs(x = xvarName) + geom_point()
print(p)
The if(is.na(stuff)) statements won't work if class is character, but I won't get into details on how to fix that, since this question is mainly about how to wait for user input. There are also ways to suppress the warning messages if the user entered something other than what is intended, but again, a bit off topic to talk about it here.
One important thing you have to watch out for is that anything you want R to print or plot, you need to wrap it with a print() function. Otherwise sourcing it won't print nor plot anything. Also, when typing in a parameter that is intended to be a string or character, don't add quotes. For example, for plotColor, type red instead of "red" in the prompt.
Most of the readline code are referenced from here:

R GUI with tcltk package: tkget() throws error when reading text property: "[tcl] bad option "get": must be cget or configure"

When I run a pure Tcl/Tk script I can read the text property of a label with the cget command:
$ wish
% label .lb -text "Read this"
pack .lb
.lb cget -text
.lb
% % Read this
If I try to do this in R using the tkget function I get an error:
library(tcltk)
tt <- tktoplevel()
lb <- tklabel(tt, text = "Read this")
tkpack(lb)
tkget(lb, "text") # TODO Does not work
> Error in structure(.External(.C_dotTclObjv, objv), class = "tclObj") :
[tcl] bad option "get": must be cget or configure.
How do I call tkget correctly (there is no proper documentation available)?
Or how could I read the current value of the text property another way?
The solution is:
library(tcltk)
tt <- tktoplevel()
lb <- tklabel(tt, text = "Read this", padx=10)
tkpack(lb)
tclvalue(tkcget(lb, "-text"))
tclvalue(tkcget(lb, "-padx"))
tkdestroy(tt)
Lessons learned:
Don't mix up tkget with tkcget (the former is the get command of a text widget, the latter is a generic command to read widget properties.
The widget property that you want to read must be specified as string with a hyphen (this is different from the way you specify the same property during creation of the widget in R using tcltk - see the padx example in the code above).
As usual: You have to convert the result of tkcget from a TCL value into an R value using the tclvalue function.

gcombobox (with Gtk2) event looping

The following code shows that assigning an item vector to gcombobox will result in looping of the gcombobox handler over each element of the existing item vector (try clicking, for example, "a" or "b" and you'll see the multiple printed messages from the gcombobox). If b2 is changed to a gradio button then this loop doesn't happen. Also, if the tcltk toolkit is used then we don't have an issue either. This is causing problems for me in a GUI where the handler for b2 is more complex and manipulates some large data. Any suggestions to prevent this looping would be great!
options("guiToolkit"="RGtk2")
library(gWidgets)
w=gwindow()
b1=gradio(c("a","b"),container=w)
b2=gcombobox(c(1:2),container=w)
addHandlerClicked(b1,handler=function(h,...) b2[,]=c(1:10))
addHandlerClicked(b2,handler=function(h,...) print("clicked b2"))
You can block the handlers then unblock as with:
w=gwindow()
b1=gradio(c("a","b"),container=w)
b2=gcombobox(c(1:2),container=w)
id = addHandlerClicked(b2,handler=function(h,...) print("clicked b2"))
addHandlerClicked(b1,handler=function(h,...) {
blockHandler(b2, id)
b2[,]=c(1:10)
unblockHandler(b2, id)
})
I flipped the order of assignment to get the handler id.
Alternatively, in gWidgets2 (still just on Github) it just works, as this assignment of selectable items for b2 isn't setting the selected value of b2. (Which you might want to do manually)
options("guiToolkit"="RGtk2")
library(gWidgets2)
w=gwindow()
g = ggroup(cont=w) ## only one child for a gwindow instance is enforced
b1=gradio(c("a","b"),container=g)
b2=gcombobox(c(1:2),container=g, expand=TRUE)
id = addHandlerChanged(b2,handler=function(h,...) print("clicked b2"))
addHandlerChanged(b1,handler=function(h,...) {
b2[]=c(1:10)
})

Resources