• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

jFormattedTextField

 
Ranch Hand
Posts: 53
1
Mac OS X Netbeans IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am using a jFormattedTextField to enter a price. This seems straightforward, but every time I enter a dollar value (e.g.13.45) The text shows in the box until I change focus (either "enter", tab, or mouse reposition). When reading the formatted text I consistently get a null, regardless of how it is read. The formatting factory items are "currency" and "¤#,##0".



listEach is a double value defined elsewhere. I added the line where Object le is retrieved to be able to see just what's being returned. It is null. The second line always generates an error because the null value is read. Sorry for bringing up such a dumb question, but I am baffled.


 
Bartender
Posts: 10980
87
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Bill Babbitt wrote:The text shows in the box until I change focus (either "enter", tab, or mouse reposition).


...then what does it show?

Are you executing that snippet in a PropertyChangeListener? (we need to see more of the code)
 
Marshal
Posts: 4698
587
VSCode Eclipse IDE TypeScript Redhat MicroProfile Quarkus Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The javadoc for JFormattedTextField.html#getValue says:

Returns the last valid value. Based on the editing policy of the AbstractFormatter this may not return the current value. The currently edited value can be obtained by invoking commitEdit followed by getValue.

It sounds like you need to save/commit the value if you want to be able to reference it later.
 
Bill Babbitt
Ranch Hand
Posts: 53
1
Mac OS X Netbeans IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I read somewhere that losing focus or return automatically issues cloeEdit(). Anyway, I tried inserting closeEdit() with several actions. They were never hit. What action event happens after entering a value?
 
Marshal
Posts: 80247
426
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think we need to see more details please.
 
Rancher
Posts: 3324
32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Have you tried using the setFocusLostBehavior(...) method.
 
Bill Babbitt
Ranch Hand
Posts: 53
1
Mac OS X Netbeans IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, here's the deal, no matter what I do to get the double value from the jFormattedTextField, jCost, I get the following error:

Cannot invoke "java.lang.Number.doubleValue()" because the return value of "javax.swing.JFormattedTextField.getValue()" is null
at com.babbittengineering.formrttedtext.NewJFrame.jCostFocusLost(NewJFrame.java:109)

The line simply returning an Object gets a null.

Here is the whole test program:


I have theFocusLostBehavior property set to COMMIT.
 
Sheriff
Posts: 28368
99
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You have added jCost to the GUI twice. I don't know why you did that but you should only put a component into the GUI tree once. You can see the kind of problems that result.
 
Ron McLeod
Marshal
Posts: 4698
587
VSCode Eclipse IDE TypeScript Redhat MicroProfile Quarkus Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I haven't worked with Swing for a long time so I can't provide an answer, but here's some things to try which may help you find the solution that you need:

When you create your instance, provided a formatter for the view:
Rather than have the formatter perform the transformation on commit, just handle that yourself:
 
Ron McLeod
Marshal
Posts: 4698
587
VSCode Eclipse IDE TypeScript Redhat MicroProfile Quarkus Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This is kinda a hack, but you could use the component's formatter to format the result:
 
Bartender
Posts: 5584
213
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:You have added jCost to the GUI twice. I don't know why you did that but you should only put a component into the GUI tree once. You can see the kind of problems that result.


No, that is not the case. It is just the working of the GroupLayoutManager, that does a two-pass layout: first horizontally, then vertically. I have more than once asked to an OP to hide the GroupLayout-code, since that is unreadable and adds nothing to the problem.

@OP
Apart from Rons remarks, you do indeed set the FocusLostBehaviour to 'COMMIT', but you are also adding a FocusLost-Listener. Now, that Listener is invoked BEFORE the commit takes place, so add this to the beginning of that FocusListener:

You can then leave out setting the FocusLost-property
 
Piet Souris
Bartender
Posts: 5584
213
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Edit:

I had changed the formatter to just 'getInstance()' instead of 'getCurrencyInstance()'. Then that NPE disappears. When I change it back to 'getCurrencyInstance()' I still get an error, this time a ParseError. So there is something to add to that getCurrencyInstnce. Looking further.
 
Bill Babbitt
Ranch Hand
Posts: 53
1
Mac OS X Netbeans IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Piet, I tried your suggestion. It makes sense. Sadly, it throws a parse exception at jCost.commitEdit().


Ron McLeod, Thanks. I figured I could do that hack, but I also have date formatting in another place and would like to use the getValue() method of the jFormattedTextField class.
 
Author
Posts: 986
3
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm going to try to be helpful without reading this entire thread thoroughly, which is a recipe for disaster but here we go.

First thing, be aware that calling commitEdit() is supposed to throw ParseException sometimes. That it is happening is not necessarily a problem. Especially since you have called jCost.setFocusLostBehavior(javax.swing.JFormattedTextField.COMMIT), which means that you want the field to retain invalid content even when it loses focus.

Second, I'd like to reinforce what Mr. McLeod said about calling commitEdit() before calling getValue(). This is a good idea. In fact, on page 713 of my book (Java Swing 2nd Ed., O'Reilly, 2003) it says

value [meaning the property returned by getValue()] is the most recent valid content of the field, which may not be the current content of the field if an edit is in progress. Because of this, it is usually wise to call the field's commitEdit() method before calling getValue().*

*Especially if the focusLostBehavior property is set to PERSIST. In other cases it is likely that the field lost focus (causing its value to be committed or reverted) when the user clicked on the button or other GUI element that resulted in this call to getValue(). Calling commitEdit() is easy enough that it makes sense to do it unless you're sure that it isn't required.


But I should point out that I'm not saying that commitEdit() should be called in a FocusListener. In fact, that sounds like a bad idea. I simply mean that every place in your existing code where you call getValue(), you should call commitEdit() on the previous line.

How are you actually creating your currency field? Is it like this?
disclaimer: I'm only one of several authors of my book, but I'm the one who happened to write the JFormttedTextField chapter (chapter 20). However that was two decades ago and I haven't used them much since then. For this post I had originally written two paragraphs which, upon further reflection, I decided was incorrect so I removed them.
 
Bill Babbitt
Ranch Hand
Posts: 53
1
Mac OS X Netbeans IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Brian, thank you very much for helping. After spinning my wheels long enough, I just went with retrieving a string and converting it to a double currency value. Getting value sounds not only complicated but risky. If you do manage to get a value, it may not be the value you expected. The string seems to persist at least long enough to get a reliable value.

Below is my FormatterFactory for jCost. It got truncated in the source code printout.

   jCost.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(java.text.NumberFormat.getCurrencyInstance())));


BTW: Your book is my bible for Java Swing. I wish someone (you?) would do one with Netbeans Java Swing. Netbeans does a lot of behind-the-scenes stuff that can't be undone, and the properties aren't always clear.
 
Bill Babbitt
Ranch Hand
Posts: 53
1
Mac OS X Netbeans IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There are problems even using the string return. I think I found the culprit. Currency is in dollars and cents. When I enter a value with a decimal (e.g.12.34), the decimal point is seen as an invalid character. So ... is there a simple way to convert this? I really need to input true dollars and cents.
 
Carey Brown
Bartender
Posts: 10980
87
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What is "true" dollars and cents?

Usually a BigDecimal is used for currency.
 
Bill Babbitt
Ranch Hand
Posts: 53
1
Mac OS X Netbeans IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Okay, I finally worked out the solution:

 
Brian Cole
Author
Posts: 986
3
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I still don't know how you're instantiating your JFormattedTextField but, if it were me doing it, it would look something like this:


Note that in lines 26–40 I override the field's commitEdit() method. You could take those lines out and it would work, sort of. The problem is that if the user types a plain number into the field, without the leading '$' character (or whatever is expected for the local currency) then NumberFormat.parse() fails and the field's value will not be set. Overriding commitEdit() like this is somewhat ugly, but allows the user to set the value with an undecorated number.

I should point out that if I were doing this for real, I wouldn't have the money field, which needs to be synchronized with the field's value, as this code does with the PropertyChangeListener. I would simply let the value reside inside field, and call getValue() when it was needed [perhaps preceded by commitEdit()].
reply
    Bookmark Topic Watch Topic
  • New Topic