Why is JFormattedTextField restoring previous value? - java

I am using a JFormattedTextField, when i try to delete the value in the field, it automatically restores the previous value.
What is the reason for this behaviour and how can i stop it restoring the value?
This is the code for JFormattedtextField.
jFormattedTextField2 = new javax.swing.JFormattedTextField(new DecimalFormat("###,###.##"));

It happens because JFormattedTextField allows configuring what action should be taken when focus is lost using the setFocusLostBehavior method.
These are the actions.
Description
JFormattedTextField.REVERT - Revert the display to match that of getValue, possibly losing the current edit.
JFormattedTextField.COMMIT - Commits the current value. If the value being edited isn't considered a legal value by the AbstractFormatter
that is, a ParseException is thrown, then the value will not change,
and then edited value will persist.
JFormattedTextField.COMMIT_OR_REVERT - Similar to COMMIT, but if the value isn't legal, behave like REVERT.
JFormattedTextField.PERSIST - Do nothing, don't obtain a new AbstractFormatter, and don't update the value.
**** The default is JFormattedTextField.COMMIT_OR_REVERT so when you enter an invalid value, it's reverted and you get the previous
consistent state**

Related

JSpinner returns default value instead of typed one

I have a JSpinner with SpinnerNumberModel (1, Double.MIN_VALUE, Double.MAX_VALUE, 0.01)
If I type directly to JSpinner - 1000, click OK in some dialog, and get spinner.getValue() it will return '1' instead of 1000.
If I type 1000 and change focus to somewhere else like clicking on JDialog's emty space and read value after that it will be correct=1000. If I will change values with spinner's arrows - value will be correct too.
How to fix Jspinner so it will support typing values without changing focus to somewhere else first before getting it's value?
Java JDK 1.6.0_23
The JSpinner JavaDoc describes why this happens and how to solve it.
A JSpinner has a single child component that's responsible for displaying and potentially changing the current element or value of the model, which is called the editor. The editor is created by the JSpinner's constructor and can be changed with the editor property. The JSpinner's editor stays in sync with the model by listening for ChangeEvents. If the user has changed the value displayed by the editor it is possible for the model's value to differ from that of the editor. To make sure the model has the same value as the editor use the commitEdit method, eg:
try {
spinner.commitEdit();
}
catch (ParseException pe) {{
// Edited value is invalid, spinner.getValue() will return
// the last valid value, you could revert the spinner to show that:
JComponent editor = spinner.getEditor()
if (editor instanceof DefaultEditor) {
((DefaultEditor)editor).getTextField().setValue(spinner.getValue();
}
// reset the value to some known value:
spinner.setValue(fallbackValue);
// or treat the last valid value as the current, in which
// case you don't need to do anything.
}
return spinner.getValue();

Constrain numeric value in JTextField to a specific range, with defaults

Not sure how to write this in JAVA...
I need to code that will insert a default value (say 50) if user keys in a value outside of a given range of 10-100 feet. I have it working for errors if blank or non integer is entered or value is outside the range but cannot figure out how to integrate a default.
What I have that works is
JPanel panel1 = new JPanel();
panel1.setLayout(new FlowLayout());
poolLength = new JTextField(10);
panel1.add(new JLabel("Enter the pool's length (ft):"));
panel1.add(poolLength);
What I want to add is something like this
If poolLength <10 or >200 then poolLength = 100
Else this.add(panel1);
The simplest way is to get the text during e.g. an ActionEvent, parse it and reset the text if it's outside the range.
jTextField.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
boolean isValid = true;
try {
int intVal = Integer.parseInt(jTextField.getText());
if (intVal < 10 || intVal > 200) {
isValid = false;
}
} catch (NumberFormatException x) {
// user entered something which is not an int
isValid = false;
}
if (!isValid) {
jTextField.setText("100");
}
}
});
Also see How to Use Text Fields.
Another way would be to use a spinner which does something like this by default.
disclaimer: I do not know Swing well, actually, I dont remember much at all..
Maybe you simply need to attach a validator to your JTextField?
Here you have an example, however please notice that in that post they check for the length of the text, not the contents. But having the text, you can easily parse it as a number and check if it is greater/lower than the bounds.
As you see in that post, by returning true/false you will prevent the user from entering a wrong value - ie. too small. Now, when wrong value is detected, then, instead of returning 'false', maybe it is possible to simply myjtextfield.setText("50.0") on that input? That may do exactly what you wanted.
really, be careful with those "maybe"s: I do not know Swing, but from general UI framework design, trying to "setText" may:
throw an exception: many frameworks think it's quite evil to change the field's value during validation and defend themselves against it
cause strange issues when editing: if that JTextEdit calls validation upon every single change of the text, you will notice odd things when trying to, i.e. select-all, delete, write 123. You'll end up with 50.0123 or 12350.0 as the JTextEdit might try to validate the intermediate empty text after deletion and coerce it to "50.0"..
or, it may just work.
So, if your time is critical, just try it. Maybe I guessed well. But, if you have some time to spare, wait until someone checks that I didn't write any nonsense.
Use a JSpinner instead.
It will not behave exactly as described, but provide a better user experience. The user can adjust the value with the ↑/↓ buttons. If they type a value outside the specified range, it will revert to the last valid value when the field loses focus.

Mongodb java api: WriteResult#getN()

I'm writing some Java code using MongoDB with Java API and I'm unsure of some part of the Javadoc.
In a multi-thread context I use DBCollection.html#update(com.mongodb.DBObject, com.mongodb.DBObject) to update a unique document, but I saw that two threads could try to write concurrently. In this context, I observed that only one write was done, as Mongodb seems to use optimistic write lock, but I wanted to find out programmatically in which thread the write was the one who wrote, and which one was not. As a "no update" behavior was silent (I mean no exception or something), I searched into the API some way to answer my issue and after some tests found out this method: WriteResult#getN()
public int getN()
Gets the "n" field
Returns:
The description is, hum... not really exhaustive. My tests showed that the thread that win the write has a getN() that return 1, and the other 0.
So my question is: Could someone confirm this ?
From the GetLastError() documentation
The return value from the command is an object with various fields. The common fields are listed below; there may also be other fields.
ok - true indicates the getLastError command completed successfully. This does NOT indicate there wasn't a last error.
err - if non-null, indicates an error occurred. Value is a textual description of the error.
code - if set, indicates the error code which occurred. connectionId - the id of the connection
lastOp - the op-id from the last operation
For updates:
n - if an update was done, this is the number of documents updated.
So in this context, 'get "n" field' means get n which is the number of documents updated. Without "multi" being set to true it can only be either 0 or 1.

Java StackOverflowError

...
float value = Float.parseFloat((String)model.getValueAt(e.getLastRow(), 1));
DecimalFormat dec = new DecimalFormat("#.###");
model.setValueAt(dec.format(value), e.getLastRow(), 1);
...
at the third line i'm getting the stackOverflowError exception. What I'm intending to do is getting a JTable cell value from an Object, converting it to a float, limiting it to 3 decimal places, and finally convert to String and set the value with 3 decimal places at the cell.
I guess the problem is I'm changing the value, and entering the function again and again. So the StackOverflow is due to that. Question is, how can i fix this?
Complete function at: Java: Converting data types
(Sorry for posting twice... It was a different question, and the solution drove me to a different problem)
The problem is that setValueAt() will, as part of its implementation call tableChanged() on all registered listeners, including this one.
In order to avoid this, simply check whether the value in the cell is already in the desired format as the first thing in your method, and don't do anything if it is.
Just don't call model.setValueAt() if value of the cell is not changed.
It should stop the recursion.
I think this task is usually accomplished by setting a custom editor to the table. So that it formats all input data to a desired form. See this answer.
Perhaps you need something like
String text = (String) model.getValueAt(e.getLastRow(), 1);
String text2 = new DecimalFormat("#.###").format(Float.parseFloat(text));
if (!text.equals(text2))
model.setValueAt(dec.format(value), e.getLastRow(), 1);

J2ME TextField Exception

When I instantiate a textField, I have a number in it that I want to be the default text. The problem is, I can't seem to be able to place that value into the textfield without getting an error. The strange thing about it is that the same TextField is what I use to set the value of the variable containing the number.
TextField myTF = new TextField("Number", value, 10, TextField.NUMERIC);
When I run this code, I receive an exception stating that value doesn't match the constraints of TextField.NUMERIC. However, when I check the vale of the value of the variable, I get the following output:
value = 1234567890
value.length() = 10
The value is set by the same TextField, saved to the phone that I am working on, and when loaded from the phone's settings, throws an exception.
This is definitely a JVM bug. If a TextField returned a string, it must be able to accept it. The only thing I can advice is to play a bit with the size of the field or the constraints. You haven't specified the device you are using, there could be some new firmwares for it with bugfixes.
a potential workaround to your problem could be to instantiate the field with a null value and then set the text afterwards.
TextField myTF = new TextField("Number", null, 10, TextField.NUMERIC);
myTF.setString(value);
I have the same problem. The cellphone is trying to store the field value as an int, and the maximum int value is (2^31) - 1 = 2,147,483,647, which is one digit short of what you (and me) need. Workaround, make your field of type text and set a charset of IS_LATIN_DIGITS. Cheers.
My idea is you try it
String str=""+value;
TextField myTF = new TextField("Number",str,10,TextField.NUMERIC);

Categories