How to use BigDecimal in swing GUIs? - java

I'm using BigDecimal to represent product prices in a Java SE application.
What swing component(s) should I use in order to allow the user to input numbers with only two decimal places and bound it to a BigDecimal variable/Object's property. (Checking that as the user types)?
I've been playing with JTextField, JFormattedTextField, NumberFormatter, MaskFormatter but I can't work it out.
Is there any combination and configuration of those components to do that? or should I extend the MaskFormatter, the JTextField, ...?

I hate to necro these really old threads on stuff, but my understanding is StackOverflow cries inside every day an answer remains unsolved.
so you can checkout the code here: http://www.java2s.com/Code/Java/Swing-JFC/ABigDecimalobjectcustomformatter.htm
basically set-up to a JFormattedTextField to use a DecimalFormat

I'm not quite sure what you are trying to do, but there is a BigDecimal constructor which takes Strings as parameter (similar to e.g. Double.parseDouble(String s)):
try
{
BigDecimal decimal = new BigDecimal(yourJTextField.getText());
}
catch (NumberFormatException nfe)
{ /* error handling */}
See JavaDoc for BigDecimal for more information.
Edit: If checking/validating the user's input into the textfield, either check it manually or use a Validator (see Google results for "JTextField Validator")

Related

How to customize number format in freemarker?

I am using freemarker and trying to display numbers in this format: $3,343,434.00 for example. This was easily taken care of by using ${total?string.currency} (assuming "total" is some number).
However, when I have negative numbers, it's showing them like this: ($343.34) instead of this: -$343.34. I need the negative sign instead of the parenthesis. Is there a way I could customize the formatting so it does everything that the string.currency did but replace the negative value behavior? I am relatively new to freemarker, so detailed responses are appreciated!
You can also try ?string(",##0.00"). However in this case you need to explicitly add $ and - sign would be after $ in case of negative numbers.
<#local total = 3343434/>
$ ${total?string(",##0.00")} //$ 3,343,434.00
<#local total = -3343434/>
$ ${total?string(",##0.00")} //$ -3,343,434.00
OR in case if you want what was expected you can replace the strings.
<#local total = -3343434/>
<#local total = "$ " + total?string(",##0.00")/>
${total?replace('$ -','- $')} //- $3,343,434.00
Update: Since FreeMarker 2.3.24 you can define named custom number formats, which can be an alias to a number format pattern (or even a formatter implemented in Java, but that level of flexibility isn't needed in this case). So add a custom number format called "money" as an alias to "ยค,##0.00" to the FreeMarker configuration, and then you can write something like ${total?string.#money}. See: http://freemarker.org/docs/pgui_config_custom_formats.html
Currently FreeMarker just uses the formatting facility of the Java platform, so it's only as configurable as that (assuming you want to use ?string and ?string.somethingPredefiendHere). Which is not much... but, in general, the formatting categories provided by the Java platform is not fine-gradient enough anyway, I mean, you don't have application-domain categories like, price-of-product, a salary, a price on the stock, etc. (This demand is more frequent with non-currency numbers though.) So I think, generally, you want to make a formatter function, that you can use like ${salary(someNumber)}, ${price(someNumber)}, etc. Those functions can be implemented in a commonly #included/#imported template like a #function or in Java by using #assign salary = 'com.example.SalarayMethod'?new() in place of #function, where com.example.SalarayMethod is a TemplateMethodModelEx.
How about taking a mod of your number, convert it to the required string format and finally add a '-' prefix to the final string. You can retain the default format in just two steps.
Freemarker uses the currency formatting provided by the Java platform.
It requires a little tweaking of the DecimalFormat returned by NumberFormat.getCurrencyInstance() (which is what is called when you call .currency). You can see examples of it here.
However, that said it will likely be more effective for you to create a macro in freemarker to call which will handle your specific formatting.
Sorry for not having an example of what that macro would look like, but it's a good starter into macros in freemarker since you are just learning.
You might investigate if you can supply a custom format using the exposed configuration for number formats that will meet your needs.
If you want to maintain the default currency formatting (in case you need to use a locale other than '$'), you can just replace the parentheses like so:
${transaction.amount?string.currency?replace("(","-")?replace(")","")}
This will work without error regardless of if a number is negative or positive.
TIP: Make sure the number is actually a number with the ?number directive before converting to a currency format

textinput restrict to accept number with four decimal precision

I have a textfield in which I want to restrict user to enter only valid number with 14 digit before .(dot) and 4 digit after .(dot).
I have tried it using :
<mx:TextInput id="txtValue1" restrict="[0-9]*\.?[0-9]" maxChars="19"/>
Its not working for restriction 4 digit after .(dot).
A more common way would be to use a NumberValidator, and set the precision attribute of the validator to 4. Also, set the maxValue of the NumberValidator to whatever suits, then set the source of the NumberValidator to the textInput id. That should work I'd say, and it will also allow you to set the error fields of the validator which will pop up beside the textInput if incorrect number is entered
you can view and download a code (this works!) in my public repository from this LINK.
Basically, i created a class (NumberInput) based on TextInput class from Adobe, the diferrence in both classes was the textFieldChanged method, i add a call here to myFormat function(). This function does what you're needing.
Be careful with this class, do not use it as the final solution but I will anyway to find what you need. Check the SWF called NumberInputTest.swf, source code is in src\NumberInput.as.
I hope this help you. Sorry for my english :D.

Java: (int)(float)Float.valueOf(s) or Float.valueOf(s).toInt()

I just bumped into this little problem and I wanted the input of other people on this
I was wandering what was the best solution to convert a String to an int
(int)(float)Float.valueOf(s)
or
Float.valueOf(s).toInt()
s is a String inputed from a textfield so I can not guarantee that it is necessarily an int
my instincts is that the double cast is ugly and should be avoided
Your input?
Your requirements are unclear:
If you are expecting an integer and don't want to allow the user to enter a number with a decimal point in it, simply use Integer.valueOf(String) or Integer.parseInt(String) and catch the NumberFormatException.
If you want to allow numbers with decimal points, then use Float.valueOf(String) or Float.parseFloat(String).
If you simply want to truncate the float to an int then either Float.intValue() or two casts are equivalent. (The javadoc for intValue explicitly states this.)
If you want to round to the nearest int, use Math.round() instead of a cast.
You should catch NumberFormatException whatever approach you take, since the user could enter rubbish that is not a valid base-10 number (with or without a decimal point) ... or that exceeds the bounds of the number type.
(I suppose that you could use a regex or something to check the String before trying to convert it, but it is simpler to just let the exception happen and deal with it. The exception efficiency issue is unlikely to be a practical concern in this use-case.)
On your original question as to whether intValue() is better than two casts: it is a matter of style. The two approaches do the same thing ... according to the javadoc. It is possible that one will be slightly more efficient than the other, but:
that shouldn't be a concern for your use-case, and
the only way to know for sure would be to profile the two alternatives on your execution platform ... and frankly it is not worth the effort.
You should use Integer.valueOf(..), and catch the NumberFormatException (if the string cannot be parsed as an integer).
Integer.parseInt(string) would be best
int x = Integer.parseInt(s);
Would be best to check if the string is an int before calling this.
As others pointed out, its just matter of style not performance... but if you are worried about performance you should validate the text field data in browser itself by javascript using a regex
^[0-9]*$
which would allow only integers to be submitted to your back-end code and hence improving performance by avoiding one network trip. Still you should validate the data in back-end, for that you can use
Integer.parseInt(String s) throws NumberFormatException

Rounding Half Up with Decimal Format in Android

I want to set the Rounding Mode to HALF_UP on my DecimalFormat, but eclipse is telling me that setRoundingMode() is not available on the DecimalFormat class. My project properties (and the overall Eclipse properties) are using the 1.6 compiler. The developer.android.com site says that I can use either Java 5 or 6 so I'm not sure what the problem is.
import java.math.RoundingMode;
import java.text.DecimalFormat;
completedValueFormatter = NumberFormat.getNumberInstance();
DecimalFormat completedDecimalFormat = (DecimalFormat)completedValueFormatter;
completedDecimalFormat.setRoundingMode(RoundingMode.HALF_UP);
I've also tried using the android tools to generate an ant-based project, tried this code in the project and also got the same compile error. So it doesn't appear to be related to Eclipse. It seems related to the Android API.
Any suggestions?
This doesn't truly answer why I can't use the Java 6 .setRoundingMode(RoundingMode) method in DecimalFormat, but it is at least a work-around.
int numDigitsToShow = this.completedValueFormatter.getMaximumFractionDigits();
BigDecimal bigDecimal = new BigDecimal(valueToBeRounded);
BigDecimal roundedBigDecimal = bigDecimal.setScale(numDigitsToShow, RoundingMode.HALF_UP);
return this.completedValueFormatter.format(roundedBigDecimal.doubleValue());
I create a BigDecimal with the value I need to round, then I get a BigDecimal of that value with the scale set to the number of digits I need to round my values to. Then I pass that rounded value off to my original NumberFormat for conversion to String.
If anyone has a better solution, I'm all ears!
Here is what I suspect the problem is, (assuming I am reading the docs properly) and its a doozy:
According to the java.text.DecimalFormat API documentation, you are not actually getting the Runtime Implimentation of the Java 1.6 RE, but are getting an android "Enhanced Version" that clearly doesn't include the setRoundingMode, which frankly bites.
"This is an enhanced version of DecimalFormat that is based on the standard version in the RI. New or changed functionality is labeled NEW."
A weakness in Java for many many many years has been the DecimalFormat class defaulted to HALF_ROUND_UP and had no way to change that, until JVM 1.6. Pity to see Android is keeping this need to kludge alive.
So looks like we are stuck Kludging BigDecimal scale Settings to format output all over any app that needs it, instead of simply being able to rely on a formatter call alone to get the job done. Not the end of the world, but very disappointing Google.
Of course that same doc says that setRondingMode() works, so perhaps this is a all out BUG??
I guess this would be the best option
http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Math.html#ceil(double)

help regarding rounding off numbers

float per = (num / (float)totbrwdbksint) * 100;
i m getting the value of per as say 29.475342 . i want it to round off upto two decimal places only.like 29.48 .how to achieve this?
You should do this as part of the formatting - the floating point number itself doesn't have any concept of "two decimal places".
For example, you can use a DecimalFormat with a pattern of "#0.00":
import java.text.*;
public class Test
{
public static void main(String[] args)
{
float y = 12.34567f;
NumberFormat formatter = new DecimalFormat("#0.00");
System.out.println(formatter.format(y));
}
}
As Jon implies, format for display. The most succinct way to do this is probably using the String class.
float f = 70.9999999f;
String toTwoDecPlaces = String.format("%.2f", f);
This will result in the string "71.00"
If you need to control how rounding is done you should check BigDecimal ist has several rounding modes. http://java.sun.com/j2se/1.5.0/docs/api/java/math/BigDecimal.html
You need to be careful here, this answer is not related to java, it relates to all aspects of decimals in many programming languages hence it is generic. The danger lies with rounding numbers, is this, and it has happened in my experience and know that it can be tricky to deal with:
Supposing you are dealing with prices on items, the pricing you get from a retail supplier may be different to the price the computer tells you, sure it is marginally small, but it could add up to big money.
Adding a sales tax on a price can either be positive or negative, it can impact the operating margin of the profit/loss balance sheets...
If you are in this kind of arena of development, then my advice is not to adjust by rounding up/down...it may not show up on small sales of the items, but it could show up elsewhere...an accountant would spot it...Best thing to do is to simply, truncate it,
e.g. 29.475342 -> 29.47 and leave it at that, why?, the .005 can add up to big profit/loss.
In conjunction to what is discussed here...electronic tills and registers use their own variety of handling this scenario, instead of dealing with XX.XXXXXXXXXX (like computers, which has 27/28 decimal places), it deals with XX.XX.
Its something to keep in mind...
Hope this helps,
Best regards,
Tom.
you can use the formatted print method System.out.printf to do the formatted printing if that's what you need

Categories

Resources