I currently have an actionListener set up to detect whether or not the checkBox I have created is checked, and depending on this; set the value of taskType to either 'oneOff' (unchecked) or 'Routine (checked). The problem is that when the user submits the form by clicking the button, the received value is 'null' if the box is left unchecked, the only way to make the received value 'oneOff' is by checking the box and unchecking it again. How can I make the default unchecked value of the checkbox 'oneOff' - and is this even possible?
checkBox.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e)
{
if(freqComboBox.getSelectedIndex() == -1 && checkBox.isSelected())
{
freqLabel.setEnabled(true);
freqComboBox.setEnabled(true);
createTask.setEnabled(false);
}
else if(checkBox.isSelected())
{
freqLabel.setEnabled(true);
freqComboBox.setEnabled(true);
taskType = "Routine";
}
else
{
freqLabel.setEnabled(false);
freqComboBox.setEnabled(false);
freqComboBox.setSelectedIndex(-1);
taskType = "oneOff";
}
}
});
I'm having a problem with my Java code.
I need to execute my doSomething() method, which includes code that manage also global variables. The problem is that the method is invoked twice (both mouseEvent and focusEvent of my JTable are fired at the same time).
How can I execute the doSomething() method only once at a time, in a sort of mutual exclusion ?
Thanks.
addMouseListener (new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
doSomething();
}
});
addFocusListener(new FocusAdapter() {
#Override
public void focusLost(FocusEvent e){
doSomething();
}
});
JTable cells contains String with length 1 or 2.
I need to apply a setValue method (or delete the String), in the exact moment the user stops the cell editing or he writes a 2 character String.
With those listeners I know the exact time to do the setValue or to inform the user that the first character he wrote doesn't exist. So in that way I wanted to block the user's action.
In other words, I need to control the user input in order to do a setValue or delete it. FocusLost tells me when the user clicks outside the JTable Component.
MouseClicked tells me when the user clicks in the JTable Component.
When mouseClicked is invoked and the JOptionPane appears, the cell automatically lose the focus, and so also the focusLost is invoked.
public void doSomething () {
// inEdit and tableCellEdited are the global variables
if ( inEdit && tableCellEdited != null ) {
String temp = "" + tableCellEdited.getDay();
String s = tableCellEdited.getValRenderer().trim();
if (s.length() > 2) s = s.substring(4);
if ( !s.trim().isEmpty() ) {
JOptionPane.showMessageDialog(getParent(),
"Code doesn't exist" , "Error: Code doesn't exist",JOptionPane.WARNING_MESSAGE);
tableCellEdited.setRendererValue(getUltimaGG(), false);
}
else {
tableCellEdited.setRendererValue(s, false);
setValueAt(tableCellEdited, getRowFromMat(tableCellEdited.getMat()), Integer.parseInt(temp.substring(6, 8)) );
}
clearProgrammazioneDueCaratteri();
}
}
repaint();
}
It seems that the Spinner control does not update a manually typed-in value until the user explicitly presses enter. So, they could type in a value (not press enter) exit the control, and submit the form, and the value displayed in the spinner is NOT the value of the Spinner, it is the old value.
My idea was to add a listener to the lost focus event, but I can't see a way to gain access to the typed-in value?
spinner.focusedProperty().addListener((observable, oldValue, newValue) ->
{
//if focus lost
if(!newValue)
{
//somehow get the text the user typed in?
}
});
This is odd behavior, it seems to go against the convention of a GUI spinner control.
Unfortunately, Spinner doesn't behave as expected: in most OS, it should commit the edited value on focus lost. Even more unfortunate, it doesn't provide any configuration option to easily make it behave as expected.
So we have to manually commit the value in a listener to the focusedProperty. On the bright side, Spinner already has code doing so - it's private, though, we have to c&p it
/**
* c&p from Spinner
*/
private <T> void commitEditorText(Spinner<T> spinner) {
if (!spinner.isEditable()) return;
String text = spinner.getEditor().getText();
SpinnerValueFactory<T> valueFactory = spinner.getValueFactory();
if (valueFactory != null) {
StringConverter<T> converter = valueFactory.getConverter();
if (converter != null) {
T value = converter.fromString(text);
valueFactory.setValue(value);
}
}
}
// useage in client code
spinner.focusedProperty().addListener((s, ov, nv) -> {
if (nv) return;
//intuitive method on textField, has no effect, though
//spinner.getEditor().commitValue();
commitEditorText(spinner);
});
Note that there's a method
textField.commitValue()
which I would have expected to ... well ... commit the value, which has no effect. It's (final!) implemented to update the value of the textFormatter if available. Doesn't work in the Spinner, even if you use a textFormatter for validation. Might be some internal listener missing or the spinner not yet updated to the relatively new api - didn't dig, though.
Update
While playing around a bit more with TextFormatter I noticed that a formatter guarantees to commit on focusLost:
The value is updated when the control loses its focus or it is commited (TextField only)
Which indeed works as documented such that we could add a listener to the formatter's valueProperty to get notified whenever the value is committed:
TextField field = new TextField();
TextFormatter fieldFormatter = new TextFormatter(
TextFormatter.IDENTITY_STRING_CONVERTER, "initial");
field.setTextFormatter(fieldFormatter);
fieldFormatter.valueProperty().addListener((s, ov, nv) -> {
// do stuff that needs to be done on commit
} );
Triggers for a commit:
user hits ENTER
control looses focus
field.setText is called programmatically (this is undocumented behaviour!)
Coming back to the spinner: we can use this commit-on-focusLost behaviour of a formatter's value to force a commit on the spinnerFactory's value. Something like
// normal setup of spinner
SpinnerValueFactory factory = new IntegerSpinnerValueFactory(0, 10000, 0);
spinner.setValueFactory(factory);
spinner.setEditable(true);
// hook in a formatter with the same properties as the factory
TextFormatter formatter = new TextFormatter(factory.getConverter(), factory.getValue());
spinner.getEditor().setTextFormatter(formatter);
// bidi-bind the values
factory.valueProperty().bindBidirectional(formatter.valueProperty());
Note that editing (either typing or programmatically replacing/appending/pasting text) does not trigger a commit - so this cannot be used if commit-on-text-change is needed.
#kleopatra headed to a right direction, but the copy-paste solution feels awkward and the TextFormatter-based one did not work for me at all. So here's a shorter one, which forces Spinner to call it's private commitEditorText() as desired:
spinner.focusedProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue) {
spinner.increment(0); // won't change value, but will commit editor
}
});
This is standard behavior for the control according to the documentation:
The editable property is used to specify whether user input is able to
be typed into the Spinner editor. If editable is true, user input will
be received once the user types and presses the Enter key. At this
point the input is passed to the SpinnerValueFactory converter
StringConverter.fromString(String) method. The returned value from
this call (of type T) is then sent to the
SpinnerValueFactory.setValue(Object) method. If the value is valid, it
will remain as the value. If it is invalid, the value factory will
need to react accordingly and back out this change.
Perhaps you could use a keyboard event to listen to and call the edit commit on the control as you go.
Here is an improved variant of Sergio's solution.
The initialize method will attach Sergio's code to all Spinners in the controller.
public void initialize(URL location, ResourceBundle resources) {
for (Field field : getClass().getDeclaredFields()) {
try {
Object obj = field.get(this);
if (obj != null && obj instanceof Spinner)
((Spinner) obj).focusedProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue) {
((Spinner) obj).increment(0);
}
});
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
Using a listener should work. You can get access to the typed in value through the spinner's editor:
spinner.getEditor().getText();
I use an alternate approach - update it live while typing. This is my current implementation:
getEditor().textProperty().addListener { _, _, nv ->
// let the user clear the field without complaining
if(nv.isNotEmpty()) {
Double newValue = getValue()
try {
newValue = getValueFactory().getConverter().fromString(nv)
} catch (Exception e) { /* user typed an illegal character */ }
getValueFactory().setValue(newValue)
}
I used this approach
public class SpinnerFocusListener<T> implements ChangeListener<Boolean> {
private Spinner<T> spinner;
public SpinnerFocusListener(Spinner<T> spinner) {
super();
this.spinner = spinner;
this.spinner.getEditor().focusedProperty().addListener(this);
}
#Override
public void changed(ObservableValue<? extends Boolean> observable,
Boolean oldValue, Boolean newValue) {
StringConverter<T>converter=spinner.getValueFactory().getConverter();
TextField editor=spinner.getEditor();
String text=editor.getText();
try {
T value=converter.fromString(text);
spinner.getValueFactory().setValue(value);
}catch(Throwable ex) {
editor.setText(converter.toString(spinner.getValue()));
}
}
}
When clicking an Button it need to perform click action in this action should perform change event at this event source is null
My Code:
Multiview.java
#Override
public void onClick(ClickEvent event) {
if(event.getSource() instanceof PushButton)
{
PushButton pb = (PushButton)event.getSource();
if (id.equals("New")) {
int rowNO = startRow + tableModel.rows() - 1;
Window.selectedRow = rowNO;
Window.selectedNode = m_node;
Window.tabNo = multicomponentVO.tabNo;
Window.tabVO = tabfieldsVO;
Window.selectedqueryID=queryID;
Window.cVO = multicomponentVO;
Window.selectedcVO=multicomponentVO;
fireChange("viewnew");
}
}
private void fireChange(String action) {
this.action = action;
if (changeListeners != null) {
changeListeners.fireChange(new ChangeEvent(){});
}
}
Window.java
#Override
public void onChange(ChangeEvent event) {
Widget sender=(Widget)event.getSource();
if(sender instanceof Multiview)
{
// some stuff
}
My query is When firing change event in multiview.java it fires onchange in window.java but im getting event source is null.
Please anyone help to refine or resolve this query
Several issues are contributing to this.
changeListeners.fireChange(new ChangeEvent(){});
You've taken over how the even is supposed to be fired - instead of actually going through the event wiring that would do it right, you've made an object with no source, passed it to fireChange (which I bet is one of your own methods in changeListeners), though you don't have it listed, unless Multiview.fireChange is calling itself...?), and then are complaining that it has no source! Consider firing either from the widget (I'm assuming Mulitview is a widget), or making a handlerManager/eventBus inside Multiview and using that to send the event.
Next, you are firing a DOM event manually, which is a little weird - this is an event that is meant to be fired from user actions in the browser. Take a look at ValueChangeEvent<T> instead.
I have this combo box that I would like to enable or disable depending on a selection of "SDO/OD", (coded as 10 in database) in a previous combo box. When I use the following code it gives me the drop down listing, but for every choice. I want the drop down for only when "SDO/OD" is chosen. Otherwise, disable the combo box but allow the data to pass the null for the record. I don't think it is reading the Listener. My question is why is this happening? How to I handle the Listerner to accommodate such a task?
fcbRole.addSelectionChangedListener(new SelectionChangedListener<ModelData>()
{
#Override
public void selectionChanged(SelectionChangedEvent<ModelData> se)
{
fcbOfficeRegion.clearSelections();
fcbOfficeRegion.getStore().clearFilters();
if(fcbRole.getValue().equals("SDO/OD") && se.getSelectedItem() != null)
{
fcbOfficeRegion.enable();
fcbOfficeRegion.setValueField(se.getSelectedItem().get("strValue").toString());
StoreFilter<ModelData> sfRole = new StoreFilter<ModelData>()
{
#Override
public boolean select(Store<ModelData> store,
ModelData parent, ModelData item,
String property) {
String name = item.get("filterDepts");
name = getScc().cleanString(name.toLowerCase());
if (name.contains("(" + fcbRole.getValue().get("strValue") + ")"))
{
return true;
}
return false;
}
};
fcbOfficeRegion.getStore().addFilter(sfRole);
fcbOfficeRegion.getStore().applyFilters("fcbOfficeRegion");
}
else
Best of Listeners for JComboBox is ItemListener, this Listener fired events SELECTED/DESELECTED, always twice