Yes you do need to subclass NumberFormat
there is an example here
JFreeChart LogAxis Frequency/Resistance multipliers
-
04-04-2022 - |
سؤال
I'm trying to figure out how to dynamically format the values on the axes of my line chart based on the multiplier.
I'm using LogAxis for both the X and Y axes, as follows:
final LogAxis rangeAxis = new LogAxis(valueAxisLabel);
rangeAxis.setStandardTickUnits(LogAxis.createLogTickUnits(Locale.ENGLISH));
rangeAxis.setRange(0.01, 10.0); //10 mOhms to 10 Ohms
plot.setRangeAxis(rangeAxis);
final LogAxis domainAxis = new LogAxis(frequencyAxisLabel);
domainAxis.setStandardTickUnits(LogAxis.createLogTickUnits(Locale.ENGLISH));
domainAxis.setRange(100, 10000000); //100Hz to 10MHz
plot.setDomainAxis(domainAxis);
I currently have the following values on my Y axis:
0.01, 0.1, 1, 10
But would like it to display as
10mOhm, 100mOhm, 1Ohm, 10Ohm
and on the X axis I have
100, 1,000, 10,000, 100,000, 1,000,000, 10,000,000
but would like to see
100Hz, 1kHz, 10kHz, 100kHz, 1MHz, 10MHz
I know you can override the NumberFormat
used on the axis, but I haven't found a way to do so to where the NumberFormat
is overridden dynamically based on the value like this. Is this possible? Do I need to extend NumberFormat
to do this?
EDIT:
Per the accepted answer, I extended NumberFormat
as follows (Note that the implementation isn't complete but rather hacked for quick demo purposes for my boss)
public class UnitNumberFormat extends NumberFormat
{
/**
*
*/
private static final long serialVersionUID = -8544764432101798895L;
private UnitValue unitValue;
public UnitNumberFormat(UnitValue unitValue)
{
super();
this.unitValue = unitValue;
}
/*
* (non-Javadoc)
* @see java.text.NumberFormat#format(double, java.lang.StringBuffer,
* java.text.FieldPosition)
*/
@Override
public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos)
{
StringBuffer formattedValue = new StringBuffer();
BigDecimal bd = new BigDecimal(number);
BigDecimal multiplier = new BigDecimal(1);
String multiplierString = "";
if(number < 1 && number > 0)
{
multiplier = new BigDecimal(1000);
multiplierString = "m";
}
else if(number < 1000 && number >= 1)
{
multiplier = new BigDecimal(1);
multiplierString = "";
}
else if(number < 1000000 && number >= 1000)
{
multiplier = new BigDecimal(1. / 1000);
multiplierString = "k";
}
else if(number < 1000000000 && number >= 1000000)
{
multiplier = new BigDecimal(1. / 1000000);
multiplierString = "M";
}
else
{
throw new NumberFormatException("This formatter doesn't yet support values beyond Mega");
}
bd = bd.multiply(multiplier).round(new MathContext(1, RoundingMode.HALF_UP));
formattedValue.append(bd.toPlainString());
formattedValue.append(" ");
formattedValue.append(multiplierString);
formattedValue.append(this.unitValue.getUnit());
return formattedValue;
}
/*
* (non-Javadoc)
* @see java.text.NumberFormat#format(long, java.lang.StringBuffer,
* java.text.FieldPosition)
*/
@Override
public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos)
{
return null;
}
/*
* (non-Javadoc)
* @see java.text.NumberFormat#parse(java.lang.String,
* java.text.ParsePosition)
*/
@Override
public Number parse(String source, ParsePosition parsePosition)
{
return null;
}
}
and UnitValue
is as follows:
public enum UnitValue {
HERTZ("Hz"),
OHMS("Ω"),
;
private final String unit;
private UnitValue(String unit)
{
this.unit = unit;
}
/**
* @return the unit
*/
public String getUnit()
{
return unit;
}
}
المحلول