如何使用 fieldchangelistener 格式化数字
How to format number using fieldchangelistener
我想在用户在编辑字段中输入数字时设置数字格式。
我使用以下代码在用户将焦点切换到另一个控件时使用 onfocus()
函数来格式化数字:
public static String formatNumber(double number, int decimals, String digitGrouping){
Formatter f = new Formatter("en");
String rawNumber = f.formatNumber(number, decimals+1);
String rawIntString = rawNumber.substring(0, rawNumber.indexOf(".")); //Basically intString without digit grouping
StringBuffer intString = new StringBuffer();
StringBuffer decString = new StringBuffer(rawNumber.substring(rawNumber.indexOf(".")+1));
StringBuffer formattedNumber = new StringBuffer();
int workingVal = 0;
int newNum = 0;
boolean roundNext;
//Add digit grouping
int grouplen = 0;
int firstDigit;
if(rawIntString.charAt(0) == '-'){
firstDigit = 1;
}else{
firstDigit = 0;
}
for(int n=rawIntString.length()-1;n>=firstDigit;n--){
intString.insert(0, rawIntString.substring(n, n+1));
grouplen++;
if(grouplen == 3 && n>firstDigit){
intString.insert(0, digitGrouping);
grouplen = 0;
}
}
//First, check the last digit
workingVal = Integer.parseInt(String.valueOf(decString.charAt(decString.length()-1)));
if(workingVal>=5){
roundNext = true;
}else{
roundNext = false;
}
//Get the decimal values, round if needed, and add to formatted string buffer
for(int n=decString.length()-2;n>=0;n--){
workingVal = Integer.parseInt(String.valueOf(decString.charAt(n)));
if(roundNext == true){
newNum = workingVal + 1;
if(newNum == 10){
roundNext = true;
newNum = 0;
}else{
roundNext = false;
}
formattedNumber.insert(0, newNum);
}else{
formattedNumber.insert(0, workingVal);
}
}
//Now get the integer values, round if needed, and add to formatted string buffer
formattedNumber.insert(0, ".");
for(int n=intString.length()-1;n>=0;n--){
try{
workingVal = Integer.parseInt(String.valueOf(intString.charAt(n)));
}catch(Exception e){
formattedNumber.insert(0, intString.charAt(n));
continue;
}
if(roundNext == true){
newNum = workingVal + 1;
if(newNum == 10){
roundNext = true;
newNum = 0;
}else{
roundNext = false;
}
formattedNumber.insert(0, newNum);
}else{
formattedNumber.insert(0, workingVal);
}
}
//Just in case its a number like 9999.99999 (if it rounds right to the end
if(roundNext == true){
formattedNumber.insert(0, 1);
}
//re-add the minus sign if needed
if(firstDigit == 1) formattedNumber.insert(0, rawIntString.charAt(0));
if(digitGrouping.length() > 0){
if(formattedNumber.toString().indexOf(".") == -1){
//no decimal
if(formattedNumber.toString().indexOf(digitGrouping) > 3+firstDigit){
formattedNumber.insert(1+firstDigit, digitGrouping);
}
if(formattedNumber.toString().length() == 4+firstDigit){
formattedNumber.insert(1+firstDigit, digitGrouping);
}
}else{
//no decimal
if(formattedNumber.toString().indexOf(digitGrouping) > 3+firstDigit){
formattedNumber.insert(1+firstDigit, digitGrouping);
}
String intportion = formattedNumber.toString().substring(0, formattedNumber.toString().indexOf("."));
if(intportion.length() == 4+firstDigit){
formattedNumber.insert(1+firstDigit, digitGrouping);
}
}
}
//now remove trailing zeros
String tmp = formattedNumber.toString();
int newLength = tmp.length();
for(int n=tmp.length()-1;n>=0;n--){
if(tmp.substring(n, n+1).equalsIgnoreCase("0")){
newLength--;
}else{
if(tmp.substring(n, n+1).equalsIgnoreCase(".")) newLength--;
break;
}
}
formattedNumber.setLength(newLength);
return formattedNumber.toString();
}
不过,这并没有解决用户键入时格式化数字的问题。
对我来说显而易见的解决方案是重写 EditField 的绘制方法,使其显示为格式化文本。该字段的 getText 将 return "12345" 而它会显示为 "12 345" 例如。
这几乎完全满足您的需求。但是您还需要记住处理光标绘制。您不想在 5 上使用本机光标,而是在 3 上绘图。
编辑
这应该能帮到你。这里的重要部分是 paint
和 getFocusRect
。请注意,这仍然很粗糙。它不处理触摸事件(光标不会正确移动),也不会换行(必须由 layout
和 paint
方法处理)。
public class FormattedEditField extends TextField
{
public FormattedEditField()
{
setFilter(TextFilter.get(TextFilter.NUMERIC));
}
protected String getFormattedText()
{
String text = getText();
if ((text == null) || (text.length() == 0))
{
return "";
}
else
{
double nr = Double.parseDouble(text);
return formatNumber(nr, 2, ",");
}
}
public synchronized void getFocusRect(XYRect rect)
{
// Tell Blackberry where to draw the cursor
Font font = getFont();
String formattedText = getFormattedText();
int length = formattedText.length();
if (length == 0)
{
rect.x = getTextOriginX();
rect.width = font.getAdvance('1');
rect.y = getTextOriginY();
rect.height = font.getHeight();
}
else
{
int cursorPosition = getCursorPosition();
int i;
for (i = 0; i <= cursorPosition; i++)
{
if (cursorPosition == length)
{
break;
}
if (formattedText.charAt(i) == ',')
{
cursorPosition++;
}
}
if (cursorPosition >= length)
{
rect.x = getTextOriginX() + font.getAdvance(formattedText);
rect.width = font.getAdvance('1');
}
else
{
rect.x = getTextOriginX() + font.getAdvance(formattedText.substring(0, cursorPosition));
rect.width = font.getAdvance(formattedText.charAt(cursorPosition));
}
rect.y = getTextOriginY();
rect.height = font.getHeight();
}
}
protected void drawFocus(Graphics graphics, boolean on)
{
}
protected synchronized void paint(Graphics graphics)
{
int x = getTextOriginX();
int y = getTextOriginY();
String text = getFormattedText();
if (isFocus())
{
XYRect rect = new XYRect();
getFocusRect(rect);
int colour = graphics.getColor();
graphics.setColor(0x207CFE);
graphics.fillRect(rect.x, rect.y, rect.width, rect.height);
graphics.setColor(colour);
graphics.drawText(text, x, y);
graphics.invert(rect);
}
else
{
graphics.drawText(text, x, y);
}
}
// Since we are overriding the painting, we should accommodate the different drawing flags
private int getTextOriginX()
{
int x = 0;
if ((getStyle() & DrawStyle.HCENTER) == DrawStyle.HCENTER)
{
x = (getWidth() - getFont().getAdvance(getFormattedText())) / 2;
}
else if ((getStyle() & DrawStyle.RIGHT) == DrawStyle.RIGHT)
{
x = getWidth() - getFont().getAdvance(getFormattedText());
}
return x;
}
// Since we are overriding the painting, we should accommodate the different drawing flags
private int getTextOriginY()
{
int y = 0;
if ((getStyle() & DrawStyle.VCENTER) == DrawStyle.VCENTER)
{
y = (getHeight() - getFont().getHeight()) / 2;
}
else if ((getStyle() & DrawStyle.BOTTOM) == DrawStyle.BOTTOM)
{
y = getHeight() - getFont().getHeight();
}
return y;
}
// This method is from http://supportforums.blackberry.com/t5/Java-Development/Format-a-decimal-number/m-p/763981#M142257
// I don't know how good it is, since I use my own method for this
private String formatNumber(double number, int decimals, String digitGrouping)
{
Formatter f = new Formatter("en");
String rawNumber = f.formatNumber(number, decimals + 1);
String rawIntString = rawNumber.substring(0, rawNumber.indexOf(".")); // Basically intString without digit grouping
StringBuffer intString = new StringBuffer();
StringBuffer decString = new StringBuffer(rawNumber.substring(rawNumber.indexOf(".") + 1));
StringBuffer formattedNumber = new StringBuffer();
int workingVal = 0;
int newNum = 0;
boolean roundNext;
// Add digit grouping
int grouplen = 0;
int firstDigit;
if (rawIntString.charAt(0) == '-')
{
firstDigit = 1;
}
else
{
firstDigit = 0;
}
for (int n = rawIntString.length() - 1; n >= firstDigit; n--)
{
intString.insert(0, rawIntString.substring(n, n + 1));
grouplen++;
if (grouplen == 3 && n > firstDigit)
{
intString.insert(0, digitGrouping);
grouplen = 0;
}
}
// First, check the last digit
workingVal = Integer.parseInt(String.valueOf(decString.charAt(decString.length() - 1)));
if (workingVal >= 5)
{
roundNext = true;
}
else
{
roundNext = false;
}
// Get the decimal values, round if needed, and add to formatted string buffer
for (int n = decString.length() - 2; n >= 0; n--)
{
workingVal = Integer.parseInt(String.valueOf(decString.charAt(n)));
if (roundNext == true)
{
newNum = workingVal + 1;
if (newNum == 10)
{
roundNext = true;
newNum = 0;
}
else
{
roundNext = false;
}
formattedNumber.insert(0, newNum);
}
else
{
formattedNumber.insert(0, workingVal);
}
}
// Now get the integer values, round if needed, and add to formatted string buffer
formattedNumber.insert(0, ".");
for (int n = intString.length() - 1; n >= 0; n--)
{
try
{
workingVal = Integer.parseInt(String.valueOf(intString.charAt(n)));
}
catch (Exception e)
{
formattedNumber.insert(0, intString.charAt(n));
continue;
}
if (roundNext == true)
{
newNum = workingVal + 1;
if (newNum == 10)
{
roundNext = true;
newNum = 0;
}
else
{
roundNext = false;
}
formattedNumber.insert(0, newNum);
}
else
{
formattedNumber.insert(0, workingVal);
}
}
// Just in case its a number like 9999.99999 (if it rounds right to the end
if (roundNext == true)
{
formattedNumber.insert(0, 1);
}
// re-add the minus sign if needed
if (firstDigit == 1)
formattedNumber.insert(0, rawIntString.charAt(0));
if (digitGrouping.length() > 0)
{
if (formattedNumber.toString().indexOf(".") == -1)
{
// no decimal
if (formattedNumber.toString().indexOf(digitGrouping) > 3 + firstDigit)
{
formattedNumber.insert(1 + firstDigit, digitGrouping);
}
if (formattedNumber.toString().length() == 4 + firstDigit)
{
formattedNumber.insert(1 + firstDigit, digitGrouping);
}
}
else
{
// no decimal
if (formattedNumber.toString().indexOf(digitGrouping) > 3 + firstDigit)
{
formattedNumber.insert(1 + firstDigit, digitGrouping);
}
String intportion = formattedNumber.toString().substring(0, formattedNumber.toString().indexOf("."));
if (intportion.length() == 4 + firstDigit)
{
formattedNumber.insert(1 + firstDigit, digitGrouping);
}
}
}
// now remove trailing zeros
String tmp = formattedNumber.toString();
int newLength = tmp.length();
for (int n = tmp.length() - 1; n >= 0; n--)
{
if (tmp.substring(n, n + 1).equalsIgnoreCase("0"))
{
newLength--;
}
else
{
if (tmp.substring(n, n + 1).equalsIgnoreCase("."))
newLength--;
break;
}
}
formattedNumber.setLength(newLength);
return formattedNumber.toString();
}
}
我想在用户在编辑字段中输入数字时设置数字格式。
我使用以下代码在用户将焦点切换到另一个控件时使用 onfocus()
函数来格式化数字:
public static String formatNumber(double number, int decimals, String digitGrouping){
Formatter f = new Formatter("en");
String rawNumber = f.formatNumber(number, decimals+1);
String rawIntString = rawNumber.substring(0, rawNumber.indexOf(".")); //Basically intString without digit grouping
StringBuffer intString = new StringBuffer();
StringBuffer decString = new StringBuffer(rawNumber.substring(rawNumber.indexOf(".")+1));
StringBuffer formattedNumber = new StringBuffer();
int workingVal = 0;
int newNum = 0;
boolean roundNext;
//Add digit grouping
int grouplen = 0;
int firstDigit;
if(rawIntString.charAt(0) == '-'){
firstDigit = 1;
}else{
firstDigit = 0;
}
for(int n=rawIntString.length()-1;n>=firstDigit;n--){
intString.insert(0, rawIntString.substring(n, n+1));
grouplen++;
if(grouplen == 3 && n>firstDigit){
intString.insert(0, digitGrouping);
grouplen = 0;
}
}
//First, check the last digit
workingVal = Integer.parseInt(String.valueOf(decString.charAt(decString.length()-1)));
if(workingVal>=5){
roundNext = true;
}else{
roundNext = false;
}
//Get the decimal values, round if needed, and add to formatted string buffer
for(int n=decString.length()-2;n>=0;n--){
workingVal = Integer.parseInt(String.valueOf(decString.charAt(n)));
if(roundNext == true){
newNum = workingVal + 1;
if(newNum == 10){
roundNext = true;
newNum = 0;
}else{
roundNext = false;
}
formattedNumber.insert(0, newNum);
}else{
formattedNumber.insert(0, workingVal);
}
}
//Now get the integer values, round if needed, and add to formatted string buffer
formattedNumber.insert(0, ".");
for(int n=intString.length()-1;n>=0;n--){
try{
workingVal = Integer.parseInt(String.valueOf(intString.charAt(n)));
}catch(Exception e){
formattedNumber.insert(0, intString.charAt(n));
continue;
}
if(roundNext == true){
newNum = workingVal + 1;
if(newNum == 10){
roundNext = true;
newNum = 0;
}else{
roundNext = false;
}
formattedNumber.insert(0, newNum);
}else{
formattedNumber.insert(0, workingVal);
}
}
//Just in case its a number like 9999.99999 (if it rounds right to the end
if(roundNext == true){
formattedNumber.insert(0, 1);
}
//re-add the minus sign if needed
if(firstDigit == 1) formattedNumber.insert(0, rawIntString.charAt(0));
if(digitGrouping.length() > 0){
if(formattedNumber.toString().indexOf(".") == -1){
//no decimal
if(formattedNumber.toString().indexOf(digitGrouping) > 3+firstDigit){
formattedNumber.insert(1+firstDigit, digitGrouping);
}
if(formattedNumber.toString().length() == 4+firstDigit){
formattedNumber.insert(1+firstDigit, digitGrouping);
}
}else{
//no decimal
if(formattedNumber.toString().indexOf(digitGrouping) > 3+firstDigit){
formattedNumber.insert(1+firstDigit, digitGrouping);
}
String intportion = formattedNumber.toString().substring(0, formattedNumber.toString().indexOf("."));
if(intportion.length() == 4+firstDigit){
formattedNumber.insert(1+firstDigit, digitGrouping);
}
}
}
//now remove trailing zeros
String tmp = formattedNumber.toString();
int newLength = tmp.length();
for(int n=tmp.length()-1;n>=0;n--){
if(tmp.substring(n, n+1).equalsIgnoreCase("0")){
newLength--;
}else{
if(tmp.substring(n, n+1).equalsIgnoreCase(".")) newLength--;
break;
}
}
formattedNumber.setLength(newLength);
return formattedNumber.toString();
}
不过,这并没有解决用户键入时格式化数字的问题。
对我来说显而易见的解决方案是重写 EditField 的绘制方法,使其显示为格式化文本。该字段的 getText 将 return "12345" 而它会显示为 "12 345" 例如。
这几乎完全满足您的需求。但是您还需要记住处理光标绘制。您不想在 5 上使用本机光标,而是在 3 上绘图。
编辑
这应该能帮到你。这里的重要部分是 paint
和 getFocusRect
。请注意,这仍然很粗糙。它不处理触摸事件(光标不会正确移动),也不会换行(必须由 layout
和 paint
方法处理)。
public class FormattedEditField extends TextField
{
public FormattedEditField()
{
setFilter(TextFilter.get(TextFilter.NUMERIC));
}
protected String getFormattedText()
{
String text = getText();
if ((text == null) || (text.length() == 0))
{
return "";
}
else
{
double nr = Double.parseDouble(text);
return formatNumber(nr, 2, ",");
}
}
public synchronized void getFocusRect(XYRect rect)
{
// Tell Blackberry where to draw the cursor
Font font = getFont();
String formattedText = getFormattedText();
int length = formattedText.length();
if (length == 0)
{
rect.x = getTextOriginX();
rect.width = font.getAdvance('1');
rect.y = getTextOriginY();
rect.height = font.getHeight();
}
else
{
int cursorPosition = getCursorPosition();
int i;
for (i = 0; i <= cursorPosition; i++)
{
if (cursorPosition == length)
{
break;
}
if (formattedText.charAt(i) == ',')
{
cursorPosition++;
}
}
if (cursorPosition >= length)
{
rect.x = getTextOriginX() + font.getAdvance(formattedText);
rect.width = font.getAdvance('1');
}
else
{
rect.x = getTextOriginX() + font.getAdvance(formattedText.substring(0, cursorPosition));
rect.width = font.getAdvance(formattedText.charAt(cursorPosition));
}
rect.y = getTextOriginY();
rect.height = font.getHeight();
}
}
protected void drawFocus(Graphics graphics, boolean on)
{
}
protected synchronized void paint(Graphics graphics)
{
int x = getTextOriginX();
int y = getTextOriginY();
String text = getFormattedText();
if (isFocus())
{
XYRect rect = new XYRect();
getFocusRect(rect);
int colour = graphics.getColor();
graphics.setColor(0x207CFE);
graphics.fillRect(rect.x, rect.y, rect.width, rect.height);
graphics.setColor(colour);
graphics.drawText(text, x, y);
graphics.invert(rect);
}
else
{
graphics.drawText(text, x, y);
}
}
// Since we are overriding the painting, we should accommodate the different drawing flags
private int getTextOriginX()
{
int x = 0;
if ((getStyle() & DrawStyle.HCENTER) == DrawStyle.HCENTER)
{
x = (getWidth() - getFont().getAdvance(getFormattedText())) / 2;
}
else if ((getStyle() & DrawStyle.RIGHT) == DrawStyle.RIGHT)
{
x = getWidth() - getFont().getAdvance(getFormattedText());
}
return x;
}
// Since we are overriding the painting, we should accommodate the different drawing flags
private int getTextOriginY()
{
int y = 0;
if ((getStyle() & DrawStyle.VCENTER) == DrawStyle.VCENTER)
{
y = (getHeight() - getFont().getHeight()) / 2;
}
else if ((getStyle() & DrawStyle.BOTTOM) == DrawStyle.BOTTOM)
{
y = getHeight() - getFont().getHeight();
}
return y;
}
// This method is from http://supportforums.blackberry.com/t5/Java-Development/Format-a-decimal-number/m-p/763981#M142257
// I don't know how good it is, since I use my own method for this
private String formatNumber(double number, int decimals, String digitGrouping)
{
Formatter f = new Formatter("en");
String rawNumber = f.formatNumber(number, decimals + 1);
String rawIntString = rawNumber.substring(0, rawNumber.indexOf(".")); // Basically intString without digit grouping
StringBuffer intString = new StringBuffer();
StringBuffer decString = new StringBuffer(rawNumber.substring(rawNumber.indexOf(".") + 1));
StringBuffer formattedNumber = new StringBuffer();
int workingVal = 0;
int newNum = 0;
boolean roundNext;
// Add digit grouping
int grouplen = 0;
int firstDigit;
if (rawIntString.charAt(0) == '-')
{
firstDigit = 1;
}
else
{
firstDigit = 0;
}
for (int n = rawIntString.length() - 1; n >= firstDigit; n--)
{
intString.insert(0, rawIntString.substring(n, n + 1));
grouplen++;
if (grouplen == 3 && n > firstDigit)
{
intString.insert(0, digitGrouping);
grouplen = 0;
}
}
// First, check the last digit
workingVal = Integer.parseInt(String.valueOf(decString.charAt(decString.length() - 1)));
if (workingVal >= 5)
{
roundNext = true;
}
else
{
roundNext = false;
}
// Get the decimal values, round if needed, and add to formatted string buffer
for (int n = decString.length() - 2; n >= 0; n--)
{
workingVal = Integer.parseInt(String.valueOf(decString.charAt(n)));
if (roundNext == true)
{
newNum = workingVal + 1;
if (newNum == 10)
{
roundNext = true;
newNum = 0;
}
else
{
roundNext = false;
}
formattedNumber.insert(0, newNum);
}
else
{
formattedNumber.insert(0, workingVal);
}
}
// Now get the integer values, round if needed, and add to formatted string buffer
formattedNumber.insert(0, ".");
for (int n = intString.length() - 1; n >= 0; n--)
{
try
{
workingVal = Integer.parseInt(String.valueOf(intString.charAt(n)));
}
catch (Exception e)
{
formattedNumber.insert(0, intString.charAt(n));
continue;
}
if (roundNext == true)
{
newNum = workingVal + 1;
if (newNum == 10)
{
roundNext = true;
newNum = 0;
}
else
{
roundNext = false;
}
formattedNumber.insert(0, newNum);
}
else
{
formattedNumber.insert(0, workingVal);
}
}
// Just in case its a number like 9999.99999 (if it rounds right to the end
if (roundNext == true)
{
formattedNumber.insert(0, 1);
}
// re-add the minus sign if needed
if (firstDigit == 1)
formattedNumber.insert(0, rawIntString.charAt(0));
if (digitGrouping.length() > 0)
{
if (formattedNumber.toString().indexOf(".") == -1)
{
// no decimal
if (formattedNumber.toString().indexOf(digitGrouping) > 3 + firstDigit)
{
formattedNumber.insert(1 + firstDigit, digitGrouping);
}
if (formattedNumber.toString().length() == 4 + firstDigit)
{
formattedNumber.insert(1 + firstDigit, digitGrouping);
}
}
else
{
// no decimal
if (formattedNumber.toString().indexOf(digitGrouping) > 3 + firstDigit)
{
formattedNumber.insert(1 + firstDigit, digitGrouping);
}
String intportion = formattedNumber.toString().substring(0, formattedNumber.toString().indexOf("."));
if (intportion.length() == 4 + firstDigit)
{
formattedNumber.insert(1 + firstDigit, digitGrouping);
}
}
}
// now remove trailing zeros
String tmp = formattedNumber.toString();
int newLength = tmp.length();
for (int n = tmp.length() - 1; n >= 0; n--)
{
if (tmp.substring(n, n + 1).equalsIgnoreCase("0"))
{
newLength--;
}
else
{
if (tmp.substring(n, n + 1).equalsIgnoreCase("."))
newLength--;
break;
}
}
formattedNumber.setLength(newLength);
return formattedNumber.toString();
}
}