Listeners allow you to respond to a user's interaction with your dialog. If the user selects an item, presses a button, or moves their mouse, you can make your GUI respond to that event.
As a simple example, let's start with the first few components of the "Factor Analysis" dialog that we have been working with.
#make dialog dialog <- new(SimpleRDialog) dialog$setSize(500L,400L) dialog$setTitle("Factor Analysis") #add variable selector variableSelector <- new(VariableSelectorWidget) variableSelector$setTitle("data") addComponent(dialog,variableSelector,10,400,850,10) #add a list for the variables variableList<- new(VariableListWidget,variableSelector) variableList$setTitle("variables") addComponent(dialog, variableList,100,900,450, 420)
The above code makes our dialog, and adds the VariableSelector and VariableList. Instead of adding the various options below the VariableList, we will add a button.
#Add an 'Options' button JButton <- J("javax.swing.JButton") button <- new(JButton,"Options") addComponent(dialog,button,500,800,600,600)
javax.swing.JButton is part of the standard Swing Library. We wish to perform an action when this button is pressed. We can do this by creating an ActionListener, and adding it to the button. First, let's create the listener:
#Listen for the button to be pressed ActionListener <- J("org.rosuda.deducer.widgets.event.RActionListener") listener <- new(ActionListener)
All component listeners are located under org.rosuda.deducer.widgets.event , later we will enumerate all of the implemented listeners, but for now, it suffices to know that the RActionListener class responds to user actions such as button pressing.
Next we need to tell the listener what to do when the button is pressed. The actionFunction is a function that takes two parameters, and displays a message to the user with a JOptionPane.
JOptionPane <- J("javax.swing.JOptionPane") actionFunction <- function(cmd,ActionEvent){ JOptionPane$showMessageDialog(dialog,paste("Two things:\n 1. Hello from R, it's nice to see you\n 2. You pressed: ", cmd)) } listener$setFunction(toJava(actionFunction)) button$addActionListener(listener) dialog$run()
The first line loads the JOptionPane class. actionFunction like all R functions to be called by a listener takes two parameters, the first is the type of action. in this case it will be the name of the button pressed. The second is an Java object which provides a full description of the event. Next we call setFunction
on the listener and pass it our R function. It is necessary to wrap this function in toJava
because the listener needs a Java representation of the function. Finally, we add the listener to the button, so that when it is pressed, we see:
The following types of listeners can call back to R functions.
Class | Description |
---|---|
org.rosuda.deducer.widgets.event.RActionListener | User Actions |
org.rosuda.deducer.widgets.event.RCaretListener | cursor movements in text fields |
org.rosuda.deducer.widgets.event.RChangeListener | A change in the component's state |
org.rosuda.deducer.widgets.event.RComponentListener | General component events |
org.rosuda.deducer.widgets.event.RDocumentListener | Document Actions |
org.rosuda.deducer.widgets.event.RFocusListener | gaining or losing focus |
org.rosuda.deducer.widgets.event.RKeyListener | keyboard button pressing |
org.rosuda.deducer.widgets.event.RListSelectionListener | items selected in a JList |
org.rosuda.deducer.widgets.event.RMouseListener | mouse events (e.g. mousing over a component) |
org.rosuda.deducer.widgets.event.RMouseMotionListener | mouse movement |
org.rosuda.deducer.widgets.event.RMouseWheelListener | wheel actions |
org.rosuda.deducer.widgets.event.RWindowListener | window closing, opening, etc. |
Each of these classes has setFunction
and getFunction
methods which allow you to set and get the R function which you wish it to call. The R function must take two parameters. The fist one is a string describing the event, the second is a Java object inheriting from Event
.
These listeners can be registered with any Java Component by adding it with the appropriate function (e.g. object$addActionListener(actLis)
or object$addMouseListener(MLis)
). Additionally, DeducerWidgets provide a general method AddListener
which will register the listener if it is appropriate for the class, and do nothing otherwise.
The RDialogMonitor allows you to run an R function at pre-specified intervals while an RDialog is open. For example, instead of displaying a message when the number of items in the 'Factor Analysis' variable list is less than two, we might wish to simply disable the 'RUN' button. This can be accomplished by repeatedly checking whether the list contains more than two items, and setting the run button accordingly.
First we create a new RDialogMonitor
monitor <- new(RDialogMonitor,dialog,500L)
The monitor will do nothing if dialog
is not visible. Otherwise it will run a function which we specify. 500L
indicates that the function should be executed every 500ms.
runButton <- dialog$getOkayCancel()$getApproveButton() monitorFunction <-function(){ if(length(variableList$getItems())<2) runButton$setEnabled(FALSE) else runButton$setEnabled(TRUE) } monitor$setFunction(toJava(monitorFunction))
monitorFunction
checks the number of items in the list, and disables the Run button if that number is less than two. If there are two or more, the button is enabled.
Lastly, we need to tell monitor
to start running
monitor$start()
When the dialog is no longer needed, call monitor$stop()
to stop the thread from running.
For example if there is only one item in the list, it will look like this:
Note of caution: The RDialogMonitor starts a new thread and executes R commands from this new thread. Since R is not thread safe, you need to make sure that the REPL is blocked while the dialog is visible (i.e. users can not enter commands directly into the console while the dialog is open). This is taken care of if you open the dialog with dialog$run()
, and is also not an issue in the JGR console as it is completely Java based.