URCap - Choosing Swing or HTML
This article is aimed at URCap Developers.
/When to use Swing or HTML
Since version 1.3.55 the URCap SDK allows URCap developers to create their user interface in either native Java Swing, or a subset of HTML.
The purpose of this article is to outline the major differences, pros and cons, to help you decide what version to develop.
Keep in mind, that it is possible later on, to adjust your code to use the other implementation as well, if you wish to change your mind.
For converting from (old) HTML URCaps, to Swing, read the "URCap Converting to Swing" guide in the SDK.
/The executive summary
Put in short, HTML is often easier to develop, and non-Java programmers may find this easier, but offers a more limited functionality.
Swing may be more cumbersome, but provides the full UI feature-set of Java Swing, to create more advanced and sophisticated UI's.
/Choosing Swing
Swing based UI was introduced in SDK 1.3.55, and supports PolyScope version 5.0 and 3.6 and above. Hence, the robot must at minimum run this software version, to support Swing based URCaps.
Java Swing is a GUI Widget toolkit for Java, and is used widely by Java developers around the world. UR's PolyScope software is based on a Java Swing user interface.
Swing is the preferred UI technology used by URCaps. Hence, this the recommended selection for most URCaps Developers. UR will not keep developing new features to the HTML subset, as these features may be obtained with Swing.
URCaps using Swing to build their user interface can choose any UI objects, that are supported in JDK6.
This includes elements such as:
- Alterable text (JLabel), with styling (font, size, bold etc.)
- Text input fields
- Number input fields
- Special input fields (such as passoword or IP addresses)
- Buttons (JButton)
- Check boxes (JCheckBox) and radio buttons (JRadioButton)
- Dropdowns (JComboBox)
- Lists (JList) for selecting multiple items on a list
- Images
- Spinners and sliders
- Color choosers
- Tables
- Folder or file trees
- Progress bars
- Etc.
Each of the elements, can be styled in Java, to achieve the appearance desired. It should though be noted, that the user interface must comply with the URCaps Style Guide.
Typically, the code lines needed in Java will be more extensive, than the similar UI in HTML. However the richness of features provided in Swing is also far superior to HTML.
In Swing, the developer is responsible for linking the View-class (the user interface) with the Contribution-class (the controller and logic code), through public methods and callbacks associated with the various UI elements. Furthermore, the developer is responsible for handling grouping of changes, done by a user event into blocks of "Undoable Changes" - this is handled automatically in HTML.
For most UI objects in Swing, the developer have to handle re-styling objects if they switch between an enabled or a disabled state. If it is desired to develop a URCap that is compatible with both CB3 robots (PolyScope 3.6+) and e-Series robots (PolyScope 5.0+), the developer must create differing instances of styling to the UI elements manually, to satisfy both user interface look-and-feels.
/Choosing HTML
HTML based UI's have been a part of the SDK since version 1.0, any URCap will hence support this functionality.
When developing a URCap with a HTML user interface, the developer can use a limited subset of standard HTML elements and attributes.
The HTML developed in the URCap, is by PolyScope parsed into the native Swing user interface, that PolyScope is based upon.
HTML elements and attributes supported by the URCap API follows a strict subset of code, that is documented in the URCaps Tutorial.
Deviating from this subset will result in errors, e.g. scripting such as JavaScript is not supported.
Typical elements, that can be used in a URCap HTML user interface includes:
- Static and dynamically alterable text
- Text input fields
- Number input fields
- Buttons
- Check boxes and radio buttons
- Dropdowns
- Images
The URCap developer must create a linking between the HTML code (.html-file) and the Contribution-class (the controller and logic code) in Java. In HTML done by the "id" attribute, and for example by "@Input"-annotations in Java. When an event happens in the URCaps user interface, PolyScope will automatically call the associated callback in the Contribution-class, and any changes done to the data stored, will automatically be grouped into an Undoable-block, the user can later un-/redo.
Some layout management can be done using CSS styling, but in general PolyScope handles implementing the UI elements, in a way that is corresponding the the overall PolyScope look-and-feel.
/Principle of View and Contribution using Swing
This article outlines the general principle of linking the user interface (View) to the controller code (Contribution) within a URCap using Java Swing.
An important thing to note first, is that there is only loaded ONE instance of the View, while there may be multiple instances of e.g. a program node (i.e. multiple Contributions). That means, that it is important to update the user interface to reflect the selected nodes settings, when the view is opened by the user.
The general task, of the two classes are:
/View
Representing the User Interface, which is shown to the user.
Populating the UI with various UI components, such as textfields, checkboxes, buttons etc.
Receiving update calls from the Contribution, and reflect these in the View, mainly when View is opened.
/Contribution
The main objective is to be able to generate URScript (in the generateScript-call), based on the data stored in the DataModel.
Storing and keeping track of the settings of this particular node, using the DataModel.
Updating the View from the openView() method, when the node is opened.
Providing Validators for textfield keyboards, and receiving callbacks when the user interacts with the View.
That means that generally, the Contribution knows the valid data, and what is currently the state of the node.
In that respect, the Contribution will need to call into the View, whenever the openView-call happens, to update the View to reflect the correct settings of the node.
The View captures events by the user, and channels the new values into the Contribution, so these can be stored in the DataModel.
For most UI elements, the View will add an ActionListener to the UI Component, and this action listener, will call the relevant method in the Contribution.
The behavior is slightly different between Installation nodes and Program nodes. The relationship between InstallationNodeView and InstallationNodeContribution is always 1:1, since there is only one installation node active at a time. The View can then access the Contribution using the contribution-object passed in the buildUI()-method.
For program nodes, there can be multiple ProgramNodeContributions, since there can be multiple instances of the same type of node in a program. But as there is only one instance of the View, the View must use the ContributionProvider, to get the actual Contribution in focus. This is done using the "get()" method on the ContributionProvider, as this will return the Contribution of the actual node in focus.
A special case appears for textfield-objects, as these need to show a keyboard, for the user to input data. Because it is the Contribution, that positively knows what data are currently active in the DataModel, and also knows then what new values are accepted, it is the task of the Contribution to provide such a Keyboard.
That means that first the View will request a Keyboard from the Contribution. The Contribution creates a new Keyboard-object, and can subsequently add an initial value (from the DataModel) and a Validator, that determined whether an input is valid. This Keyboard is returned to the View, along with a KeyboardInputCallback, which is a public method in the Contribution. The View will then show the Keyboard, and the user can input data. When the user is done inputting data, pressing the OK button, will return the new value into the KeyboardInputCallback method, and hence the Contribution receives this value, sets the value back into the View-textfield, and store it in the DataModel.
Generally, it can be said that for each general UI component, the following methods must be implemented:
- In View: A public method, to update the value of the Component.
This should be called by the Contribution, to update the View. - In Contribution: A public method, to receive changes to a value.
This should be called by the ActionListener or similar event handler, from the View, when the user change a setting.
Particularly in respect to textfields, there is a need for:
- In View: A public method, to update the value of the JTextField.
Same approach as for general components. - In Contribution: A public method, returning a Keyboard-object to show on a textfield, when user wants to input data.
- In Contribution: A public method, that returns a KeyboardInputCallback, which is called when the data is entered by the user.
Keyboards for textfields can be of different types, such as a general String, a positive double, double, positive integer, integer, password and IP-addresses. Please refer to the "UserInput" sample in the SDK, which focus on various keyboard types, validators and linking between View and Contribution.
For a more elaborate example of how to use Java Swing in URCaps, please see the next sextion.
/How to build your UI in URCap using Swing
This article covers the most common UI examples for Swing, which includes the examples for:
- JSlider
- JComboBox
- JButton
- JRadioButton
- JTextField
- JLabel
Each example contains a short introduction, an image of the deployment in the PolyScope, the corresponding code and an explanation of the code. Do notice that each code example uses a Box component which is used for the purpose of the layout when deploying into PolyScope. The following image shows the overall view of the examples when deployed in PolyScope.
/JSlider
JSlider is a component that lets the user choose a specific value within a bounded interval. The knob seen in the JSlider is movable and can be used to position the knob to match a specific value within the specified interval.
Code Example for Jslider - View class:
//View.class
private Box createSlider(final JLabel label, final JSlider silder, int min, int max,
final ContributionProvider<samplesProgramNodeContribution> provider) {
Box box = Box.createHorizontalBox();
box.setAlignmentX(Component.LEFT_ALIGNMENT);
label.setPreferredSize(new Dimension(300, 30));
label.setMaximumSize(label.getPreferredSize());
slider.setMinimum(min);
slider.setMaximum(max);
slider.setPreferredSize(new Dimension(300, 30));
slider.setMaximumSize(slider.getPreferredSize());
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent arg0) {
int value = slider.getValue();
provider.get().setSliderDataModel(value);
}
});
box.add(slider);
box.add(createSpaceBetweenComponents(10));
box.add(label);
return box;
}
public void setTextField(String text) {
labelSlider.setText(text);
}
public void setSliderValue(int sliderValue) {
this.slider.setValue(sliderValue);
}
CODE EXAMPLE FOR JSLIDER - Contribution CLASS:
//Contribution.class
private static final String SLIDER_KEY = "slider_key";
private static final int SLIDER_DEFAULT_VALUE = 1;
public void setSliderDataModel(final int sliderValue) {
undoRedoManager.recordChanges(new UndoableChanges() {
@Override
public void executeChanges() {
model.set(SLIDER_KEY, sliderValue);
}
});
view.setTextField("Slider_value: " + model.get(SLIDER_KEY, SLIDER_DEFAULT_VALUE));
}
//Contribution.class --> openView()
view.setSliderValue(model.get(SLIDER_KEY, SLIDER_DEFAULT_VALUE));
The code snippet above shows the code example of how to create a slider in Swing. When creating a slider, it is important to set the minimum and the maximum value of the slider which is shown in the code on the following; line 12-13. Where line 14-15 sets the size of the slider.
When a user moves the knob on the slider to a desired value, we probably want to know which value the user has choosen. This is done by using a change listener on the slider; line 17-26.
In the stateChange method we call a method on the provider (The contribution class) to set the choosen value; line 23. This method is defined in the contribution class; line 6-20. The method takes the choosen value and stores it in the DataModel. The DataModel takes two parameters as input; a key and a value. The key is always the same and must be unique; line 3 where line 4 defines the default value if the value has not been set. When changing the DataModel it is important to use the UndoRedoManager.
If we do wish to set a value on the slider without moving the slider, it can be done using the setValue method in the view class ; line 40-42. This method can then be called in the contribution class, openView method, to set the value of the slider when the program starts; line 25.
/JComboBox
JComboBox is a component that combines button elements and generates a drop-down list. The drop-down list can be any type of element. The user can click on the arrow and choose from the drop-down list.
Drop-Down list:
CODE EXample for Jcombobox - View class:
//View.class
private Box createJcomboBox(JComboBox comboBox, JLabel label,
final ContributionProvider<samplesProgramNodeContribution> provider) {
Box box = Box.createHorizontalBox();
box.setAlignmentX(Component.LEFT_ALIGNMENT);
label.setPreferredSize(new Dimension(300, 30));
label.setMaximumSize(label.getPreferredSize());
comboBox.setPreferredSize(new Dimension(300, 30));
comboBox.setMaximumSize(comboBox.getPreferredSize());
comboBox.setEditable(false);
comboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent arg0) {
if (arg0.getStateChange() == ItemEvent.SELECTED) {
Integer value = (Integer) arg0.getItem();
provider.get().setSelectedValueOnComboBox(value);
}
}
});
box.add(comboBox);
box.add(createSpaceBetweenComponents(10));
box.add(label);
return box;
}
public void setComboBoxValues(Integer[] items) {
comboBox.removeAllItems();
comboBox.setModel(new DefaultComboBoxModel<Integer>(items));
}
public void setTextFieldCombo(String text) {
this.labelComboB.setText(text);
}
public void setSelectedValueComboBox(int value) {
comboBox.setSelectedItem(value);
}
CODE EXAMPLE FOR JCOMBOBOX - contribution CLASs:
//Contribution.class
private static final String COMBO_BOX_KEY = "combo_key";
private static final int COMBO_BOX_DEFAULT_VALUE = 1;
public void setSelectedValueOnComboBox(final int selectedValue) {
undoRedoManager.recordChanges(new UndoableChanges() {
@Override
public void executeChanges() {
model.set(COMBO_BOX_KEY, selectedValue);
}
});
view.setTextFieldCombo("Selected_value: " + model.get(COMBO_BOX_KEY, COMBO_BOX_DEFAULT_VALUE));
}
private void setComboBox() {
view.setComboBoxValues(values);
}
//Contribution.class --> openView()
setComboBox();
view.setSelectedValueComboBox(model.get(COMBO_BOX_KEY, COMBO_BOX_DEFAULT_VALUE));
The code example of the JComboBox shows how to retrieve and set data on a combo box in Swing. In the code; line 12-14 we set the size of the combo box and prevents the user from editing the fields in the combo box. To retrieve value choosen by the user, we define an item listener on the combo box; line 16-29. In these lines we first check if an item is selected before retrieving the value. If an item has been selected, we call the provider and sets the selected value; line 25. The method called by the provider is defined in the contribution class; line 6-16. This piece of code stores the selected value in the DataModel which can be retrieved from the DataModel again using a key; line 11 and line 15.
Inside the contribution class there is a setComboBox method; line 18-20 where it sets all the values shown in the drop down list. This method calls setComboBoxValues method defined in the view class; line 39-42 which takes an array of Integers as an input (It can also be an array of strings etc.). The setComboxBox method is then called in the method openView in the contribution class to initiate the values of the combo box when the program starts; line 25, and line 26 sets the default value by calling the method setSelectedValueComboBox defined in the view class; line 48-50.
/JButton
JButton can be used to trigger any events. It could be that a text would appear if a user clicks the button.
Code Example for jbutton - View class:
//View.class
private Box createJButton(final ContributionProvider<samplesProgramNodeContribution> provider, JLabel label) {
JButton button = new JButton();
Box box = Box.createHorizontalBox();
box.setAlignmentX(Component.LEFT_ALIGNMENT);
label.setPreferredSize(new Dimension(300, 30));
label.setMaximumSize(label.getPreferredSize());
button.setText("Click me!");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
provider.get().setButtonTextOnClick();
}
});
box.add(button);
box.add(createSpaceBetweenComponents(10));
box.add(label);
return box;
}
public void setTextForButtonDisplay(String text) {
this.labelButton.setText(text);
}
CODE EXAMPLE FOR JBUTTON - contribution class:
//Contribution.class
public void setButtonTextOnClick() {
Random random = new Random();
int randomNumber = random.nextInt(10) + 0;
view.setTextForButtonDisplay("Generated the random number: " + randomNumber);
}
The code example of a JButton shows how to create and trigger an action when a user has pressed the button. The text displayed on the button is set on line 13. To notify that the button has been pressed, we add an action listener to the button; line 15-23. Inside the action listener we call a method, setButtonTextOnClick, on the provider. It can be any method you want to trigger when the button is pressed. In this example the method being called generates a random number. The method is defined in the contribution class; line 3-11. This setButtonTextOnClick method then calls a method setTextForButtonDisplay, defined in the view class, to display the random number; line 33-15.
/JRadioButton
JRadioButton creates a button that can be either selected or not selected and if added to groups of buttons, only one of the buttons from the group can be selected.
Code example for jradiobutton:
//View.class
private Box createJRadioButton(JLabel label) {
String firstBText = "Hello";
String secondBText = "Hey";
String thirdBText = "Hi";
label.setPreferredSize(new Dimension(300, 30));
label.setMaximumSize(label.getPreferredSize());
Box box = Box.createHorizontalBox();
box.setAlignmentX(Component.LEFT_ALIGNMENT);
JRadioButton firstButton = new JRadioButton(firstBText);
firstButton.setActionCommand(firstBText);
firstButton.setSelected(true);
JRadioButton secondButton = new JRadioButton(secondBText);
secondButton.setActionCommand(secondBText);
JRadioButton thirdButton = new JRadioButton(thirdBText);
thirdButton.setActionCommand(thirdBText);
ButtonGroup group = new ButtonGroup();
group.add(firstButton);
group.add(secondButton);
group.add(thirdButton);
ActionListener radioListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Hello")) {
labelRB.setText("This command: " + e.getActionCommand());
}
else {
labelRB.setText("Other commands: " + e.getActionCommand());
}
}
};
firstButton.addActionListener(radioListener);
secondButton.addActionListener(radioListener);
thirdButton.addActionListener(radioListener);
box.add(firstButton);
box.add(secondButton);
box.add(thirdButton);
box.add(createSpaceBetweenComponents(10));
box.add(label);
return box;
}
In the code example of JRadioButton, it is important to notice that these radio buttons need to be grouped if only one radio button can be choosen at a time. The strings defined on line 5-7 are used to define the name and the command of the buttons. Line 15 shows that a button is created with the string which is displayed beside the radio button in the example shown above the code. The setActionCommand just sets the command, which can be used to trigger events if a user clicks on this radio button; line 16. The code on line 17 just sets the radio button to choosen as a default.
Grouping the radio buttons is defined on line 25-28 where each button is added to the same group. To make it possible to trigger events on these button we add an action listener on these button, which is the same action listener; line 48-50. The action listener is defined on line 30-46 where it overrides the method actionPerformed. The method checks for a command and sets the text one the label based on the command; line 37 and line 42.
/JTextField
JTextField allows user to edit text, append text to the text field and receive text from the text field.
The JTextField in the example is used as an input field. Everytime the user clicks on the box a keyboard will appear to take input as shown below.
After the input, the textfield appends the text from the input keyboard.
Code example for jtextfield - View class:
//View.class
private Box createInputBox(final JTextField textField,
final ContributionProvider<samplesProgramNodeContribution> provider) {
Box box = Box.createHorizontalBox();
box.setAlignmentX(Component.LEFT_ALIGNMENT);
textField.setFocusable(false);
textField.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
KeyboardTextInput keyboardInput = provider.get().getKeyboardForInput();
keyboardInput.show(textField, provider.get().getKeyBoardCallBack());
}
});
box.add(textField);
return box;
}
public void setINPUTtextField(String text) {
this.inputTextField.setText(text);
}
CODE EXAMPLE FOR JTEXTFIELD - Contribution class:
//Contribution.class
private static final String INPUT_KEY = "input_key";
private static final String INPUT_DEFAULT_VALUE = "not set";
public KeyboardTextInput getKeyboardForInput() {
KeyboardTextInput keyboard = keyboardInputFactory.createStringKeyboardInput();
return keyboard;
}
public KeyboardInputCallback<String> getKeyBoardCallBack() {
return new KeyboardInputCallback<String>() {
@Override
public void onOk(String value) {
final String inputText = value;
undoRedoManager.recordChanges(new UndoableChanges() {
@Override
public void executeChanges() {
model.set(INPUT_KEY, inputText);
}
});
view.setINPUTtextField("Your input is: " + model.get(INPUT_KEY, INPUT_DEFAULT_VALUE));
}
};
}
When working with JTextField in Swing, we often want to use it as an input field to retrieve input from the user, though it can be used to display text as well.This example provides an example of an input field.
To get an input we need to present a keyboard to the user. A keyboard is triggered when a user clicks the input field. The interaction between the user and the input field is being notified to the system by adding a mouse listener on the input field; line 9-15.
The keyboard is presented by calling the getKeyboardForInput method on the provider; line 12. This method is defined in the contribution class; line 6-12 where the keyboard defined is a text input keyboard, and returns an instance of itself.
Another method called on provider; line 13 is the getKeyBoardCallBack method which is also defined in the contribution class; line 14-37. This method retrieves the text entered by the user and saves it in the DataModel. The method also uses a UndoRedoManager to retrieve the value from the DataModel to be displayed in the input field (This is just to let the user know what he/she has entered) .
/JLabel
JLabel is used to as a display area for short text or an image. In the example JLabel is used to set a bold title for each example.
To show the title:
To show the result:
COde example for jlabel:
/View.class
private Box createLabel(String text) {
JLabel label = new JLabel();
Box box = Box.createHorizontalBox();
box.setAlignmentX(Component.LEFT_ALIGNMENT);
Font boldFont = new Font(label.getFont().getName(), Font.BOLD, label.getFont().getSize());
label.setFont(boldFont);
label.setPreferredSize(new Dimension(300, 30));
label.setMaximumSize(label.getPreferredSize());
label.setText(text);
box.add(label);
return box;
}
public void setTextFieldCombo(String text) {
this.labelComboB.setText(text);
}
The purpose of the code example of the JLabel is to show how to create a label to display a title of a section or a result of an input, like the two examples shown above the code example.
The method createLabel is a method used to sets a text to bold; line 10-11. The perferred size of the label and the text of the label is also set; line 13-15. This createLabel method is used to set every title of the examples seen so far.
The method setTextFieldCombo is used to set text on a label when a user has selected a value on the combo box; line 22-24. To set a text on the label we call a setText method on the label; line 23.
/Binding the HTML UI into the Contribution
This article outlines the principle, of binding HTML elements of a URCaps user interface into the Contribution (i.e. ProgramNodeContribution) for interacting with the element.
An important thing to note first, is that there is only loaded ONE instance of the user interface, while there may be multiple instances of e.g. a program node. That means, that it is important to update the user interface to reflect the selected nodes settings, when the view is opened by the user.
Consider having a program node, that consists of a number input field, a button and a textfield to represent a dynamic status.
In HTML, the general code for this UI would contain these elements:
<p> Please input number: </p> <br>
<input type="number"> <br>
<p> Click button to execute: </p>
<input type="button">
<label>status</label>
The title field of the program node is automatically inserted from the String returned from the ProgramNodeService-class "getTitle()" method call.
For the elements, such as the input field, button and label to be accessible to the Contribution, we first need to add a unique ID, to each element.
It is generally good practice, to use an ID, that reflects the functionality of the element. Hence, by adding ID's we get:
<p> Please input number: </p> <br>
<input id="numberInput" type="number"> <br>
<p> Click button to execute: </p>
<input id="executeButton" type="button">
<label id="statusLabel">status</label>
There are now three elements, in the HTML UI, that can be accessed from the Contribution-class. Respectively an InputTextField of numeric type with ID: "numberInput", a button with ID: "executeButton" and a label with the ID: "statusLabel".
In Java the first thing we should do, is to register the UI-elements, that we want to interact with, using the appropriate annotations. Hence, in the our ProgramNodeContribution-class (or for that matter InstallationNodeContribution) we add the following objects:
@Input (id= "numberInput" )
private InputTextField MyNumberInput;
@Input (id= "executeButton" )
private InputButton MyExecuteButton;
@Label (id= "statusLabel" )
private LabelComponent MyStatusLabel
This creates three new objects from the URCaps API:
- An InputTextField object named MyNumberInput, which by the annotation "@Input" is linked to the HTML element with ID: "numberInput"
- An InputButton object named MyExecuteButton, which by the annotation "@Input" is linked to the HTML element with ID: "executeButton"
- A LabelComponent object named MyStatusLabel, which by the annotation "@Label" is linked to the HTML element with ID: "statusLabel"
As these objects are now present in our Contribution, we can interact with them throughout our code, e.g. in the "openView()" method, that is called, whenever the user navigates to our view.
MyExecuteButton.setText("EXECUTE");
MyStatusLabel.setText("Nothing executed, yet...");
MyNumberInput.setText("1.2");
Remember to set the text on the button, using the "buttonObject.setText(String text)" method, otherwise the button will be blank.
At this stage, it is critical to notice, that regardless of the amount of program nodes of your type, the user inserts into the program, there will only be ONE instance of the user interface. Therefore it is critical, that you use the "openView()" method to update the user interface with the correct settings for the node in focus.
In order to be notified, whenever the user interacts with our user interface, it is possible to register a callback, for handling these changes to the UI.
A callback method for the numeric input and button would be like below:
@Input (id= "numberInput" )
public void onNumberInput(InputEvent event) {
String newValue = MyNumberInput.getText();
// Save or use "newValue" somewhere
}
@Input (id= "executeButton" )
public void onExecuteButtonClick(InputEvent event) {
// Perform some action
MyStatusLabel.setText("Executed successfully");
}
In general, the callback method should be a "public void" method, that is bound to the ID by an annotation, of where the event occurs, and that accepts the event type the element provides. In other words;
@Input (id= "someID" )
public void someMethodName(InputEvent event) {
if(event.getEventType.equals(InputEvent.ON_CHANGE) {
fooBar(foo);
}
}
It is generally a good idea to check the event type received by the method.
The InputEvent can be ON_CHANGE, ON_PRESSED or ON_RELEASED, where the ON_CHANGE event is probably best used for input fields, and ON_PRESSED and ON_RELEASED are more relevant for buttons. If this check is not performed, there is a high likelihood that the callback method be called multiple times, for each singular user interaction.
The various types of events are:
- InputEvent
Associated annotation: @Input
Types: ON_CHANGE, ON_PRESSED, ON_RELEASED
Use with: InputTextField (text or number), InputButton, InputCheckBox, InputRadioButton - SelectEvent
Associated annotation: @Select
Types: ON_SELECT
Use with: SelectDropDownList, SelectList - TouchEvent
Associated annotation: @Touch
Types: ON_PRESSED
Use with: Label (if implementing an image), Img (image)
Note: The TouchEvent, besides from just the event itself, also provides the relative pixel coordinate, of where the user touched.