📄 numberaxis.java
字号:
}
else {
LineMetrics metrics = font.getLineMetrics("Sample", frc);
maxHeight = metrics.getHeight();
}
return maxHeight;
}
/**
* Estimates the maximum tick label height.
*
* @param g2 the graphics device.
*
* @return The maximum height.
*/
protected double estimateMaximumTickLabelHeight(Graphics2D g2) {
Insets tickLabelInsets = getTickLabelInsets();
double result = tickLabelInsets.top + tickLabelInsets.bottom;
Font tickLabelFont = getTickLabelFont();
FontRenderContext frc = g2.getFontRenderContext();
result += tickLabelFont.getLineMetrics("123", frc).getHeight();
return result;
}
/**
* Estimates the maximum width of the tick labels, assuming the specified tick unit is used.
* <P>
* Rather than computing the string bounds of every tick on the axis, we just look at two
* values: the lower bound and the upper bound for the axis. These two values will usually
* be representative.
*
* @param g2 the graphics device.
* @param tickUnit the tick unit to use for calculation.
*
* @return the estimated maximum width of the tick labels.
*/
protected double estimateMaximumTickLabelWidth(Graphics2D g2, TickUnit tickUnit) {
Insets tickLabelInsets = getTickLabelInsets();
double result = tickLabelInsets.left + tickLabelInsets.right;
Font tickLabelFont = getTickLabelFont();
FontRenderContext frc = g2.getFontRenderContext();
if (isVerticalTickLabels()) {
// all tick labels have the same width (equal to the height of the font)...
result += tickLabelFont.getStringBounds("0", frc).getHeight();
}
else {
// look at lower and upper bounds...
Range range = getRange();
double lower = range.getLowerBound();
double upper = range.getUpperBound();
String lowerStr = tickUnit.valueToString(lower);
String upperStr = tickUnit.valueToString(upper);
double w1 = tickLabelFont.getStringBounds(lowerStr, frc).getWidth();
double w2 = tickLabelFont.getStringBounds(upperStr, frc).getWidth();
result += Math.max(w1, w2);
}
return result;
}
/**
* Selects an appropriate tick value for the axis. The strategy is to
* display as many ticks as possible (selected from an array of 'standard'
* tick units) without the labels overlapping.
*
* @param g2 the graphics device.
* @param drawArea the area in which the plot and axes should be drawn.
* @param dataArea the area defined by the axes.
* @param edge the axis location.
*/
protected void selectAutoTickUnit(Graphics2D g2, Rectangle2D drawArea, Rectangle2D dataArea,
RectangleEdge edge) {
if (RectangleEdge.isTopOrBottom(edge)) {
selectHorizontalAutoTickUnit(g2, drawArea, dataArea, edge);
}
else if (RectangleEdge.isLeftOrRight(edge)) {
selectVerticalAutoTickUnit(g2, drawArea, dataArea, edge);
}
}
/**
* Selects an appropriate tick value for the axis. The strategy is to
* display as many ticks as possible (selected from an array of 'standard'
* tick units) without the labels overlapping.
*
* @param g2 the graphics device.
* @param drawArea the area in which the plot and axes should be drawn.
* @param dataArea the area defined by the axes.
* @param edge the axis location.
*/
protected void selectHorizontalAutoTickUnit(Graphics2D g2,
Rectangle2D drawArea, Rectangle2D dataArea,
RectangleEdge edge) {
double zero = translateValueToJava2D(0.0, dataArea, edge);
double tickLabelWidth = estimateMaximumTickLabelWidth(g2, getTickUnit());
// start with the current tick unit...
TickUnits tickUnits = getStandardTickUnits();
TickUnit unit1 = tickUnits.getCeilingTickUnit(getTickUnit());
double x1 = translateValueToJava2D(unit1.getSize(), dataArea, edge);
double unit1Width = Math.abs(x1 - zero);
// then extrapolate...
double guess = (tickLabelWidth / unit1Width) * unit1.getSize();
NumberTickUnit unit2 = (NumberTickUnit) tickUnits.getCeilingTickUnit(guess);
double x2 = translateValueToJava2D(unit2.getSize(), dataArea, edge);
double unit2Width = Math.abs(x2 - zero);
tickLabelWidth = estimateMaximumTickLabelWidth(g2, unit2);
if (tickLabelWidth > unit2Width) {
unit2 = (NumberTickUnit) tickUnits.getLargerTickUnit(unit2);
}
setTickUnit(unit2, false, false);
}
/**
* Selects an appropriate tick value for the axis. The strategy is to
* display as many ticks as possible (selected from an array of 'standard'
* tick units) without the labels overlapping.
*
* @param g2 the graphics device.
* @param plotArea the area in which the plot and axes should be drawn.
* @param dataArea the area in which the plot should be drawn.
* @param edge the axis location.
*/
protected void selectVerticalAutoTickUnit(Graphics2D g2, Rectangle2D plotArea,
Rectangle2D dataArea, RectangleEdge edge) {
double zero = translateValueToJava2D(0.0, dataArea, edge);
double tickLabelHeight = estimateMaximumTickLabelHeight(g2);
// start with the current tick unit...
TickUnits tickUnits = getStandardTickUnits();
TickUnit unit1 = tickUnits.getCeilingTickUnit(getTickUnit());
double y = translateValueToJava2D(unit1.getSize(), dataArea, edge);
double unitHeight = Math.abs(y - zero);
// then extrapolate...
double guess = (tickLabelHeight / unitHeight) * unit1.getSize();
NumberTickUnit unit2 = (NumberTickUnit) tickUnits.getCeilingTickUnit(guess);
double y2 = translateValueToJava2D(unit2.getSize(), dataArea, edge);
double unit2Height = Math.abs(y2 - zero);
tickLabelHeight = estimateMaximumTickLabelHeight(g2);
if (tickLabelHeight > unit2Height) {
unit2 = (NumberTickUnit) tickUnits.getLargerTickUnit(unit2);
}
setTickUnit(unit2, false, false);
}
/**
* Calculates the positions of the tick labels for the axis, storing the results in the
* tick label list (ready for drawing).
*
* @param g2 the graphics device.
* @param cursor the cursor.
* @param plotArea the area in which the plot and the axes should be drawn.
* @param dataArea the area in which the plot should be drawn.
* @param edge the location of the axis.
*
*/
public void refreshTicks(Graphics2D g2, double cursor,
Rectangle2D plotArea, Rectangle2D dataArea,
RectangleEdge edge) {
if (RectangleEdge.isTopOrBottom(edge)) {
refreshHorizontalTicks(g2, cursor, plotArea, dataArea, edge);
}
else if (RectangleEdge.isLeftOrRight(edge)) {
refreshVerticalTicks(g2, cursor, plotArea, dataArea, edge);
}
}
/**
* Calculates the positions of the tick labels for the axis, storing the results in the
* tick label list (ready for drawing).
*
* @param g2 the graphics device.
* @param cursor the cursor.
* @param plotArea the area in which the plot (inlcuding axes) should be drawn.
* @param dataArea the area in which the data should be drawn.
* @param edge the location of the axis.
*/
protected void refreshHorizontalTicks(Graphics2D g2, double cursor,
Rectangle2D plotArea, Rectangle2D dataArea,
RectangleEdge edge) {
getTicks().clear();
Font tickLabelFont = getTickLabelFont();
g2.setFont(tickLabelFont);
FontRenderContext frc = g2.getFontRenderContext();
if (isAutoTickUnitSelection()) {
selectAutoTickUnit(g2, plotArea, dataArea, edge);
}
double size = getTickUnit().getSize();
int count = calculateVisibleTickCount();
double lowestTickValue = calculateLowestVisibleTickValue();
if (count <= ValueAxis.MAXIMUM_TICK_COUNT) {
for (int i = 0; i < count; i++) {
double currentTickValue = lowestTickValue + (i * size);
double xx = translateValueToJava2D(currentTickValue, dataArea, edge);
String tickLabel;
NumberFormat formatter = getNumberFormatOverride();
if (formatter != null) {
tickLabel = formatter.format(currentTickValue);
}
else {
tickLabel = getTickUnit().valueToString(currentTickValue);
}
Rectangle2D tickLabelBounds = tickLabelFont.getStringBounds(tickLabel, frc);
LineMetrics metrics = tickLabelFont.getLineMetrics(tickLabel, frc);
float x = 0.0f;
float y = 0.0f;
Insets tickLabelInsets = getTickLabelInsets();
if (isVerticalTickLabels()) {
x = (float) (xx + tickLabelBounds.getHeight() / 2);
if (edge == RectangleEdge.TOP) {
y = (float) (cursor - tickLabelInsets.bottom
- tickLabelBounds.getWidth());
}
else {
y = (float) (cursor + tickLabelInsets.top
+ tickLabelBounds.getWidth());
}
}
else {
x = (float) (xx - tickLabelBounds.getWidth() / 2);
if (edge == RectangleEdge.TOP) {
y = (float) (cursor - tickLabelInsets.bottom
- metrics.getLeading()
- metrics.getDescent());
}
else {
y = (float) (cursor + tickLabelInsets.top
+ tickLabelBounds.getHeight());
}
}
Tick tick = new Tick(new Double(currentTickValue), tickLabel, x, y);
getTicks().add(tick);
}
}
}
/**
* Calculates the positions of the tick labels for the axis, storing the results in the
* tick label list (ready for drawing).
*
* @param g2 the graphics device.
* @param cursor the cursor location.
* @param plotArea the area in which the plot and the axes should be drawn.
* @param dataArea the area in which the plot should be drawn.
* @param edge the location of the axis.
*
*/
protected void refreshVerticalTicks(Graphics2D g2, double cursor,
Rectangle2D plotArea, Rectangle2D dataArea,
RectangleEdge edge) {
getTicks().clear();
Font tickLabelFont = getTickLabelFont();
g2.setFont(tickLabelFont);
if (isAutoTickUnitSelection()) {
selectAutoTickUnit(g2, plotArea, dataArea, edge);
}
double size = getTickUnit().getSize();
int count = calculateVisibleTickCount();
double lowestTickValue = calculateLowestVisibleTickValue();
if (count <= ValueAxis.MAXIMUM_TICK_COUNT) {
for (int i = 0; i < count; i++) {
double currentTickValue = lowestTickValue + (i * size);
double yy = translateValueToJava2D(currentTickValue, dataArea, edge);
String tickLabel;
NumberFormat formatter = getNumberFormatOverride();
if (formatter != null) {
tickLabel = formatter.format(currentTickValue);
}
else {
tickLabel = getTickUnit().valueToString(currentTickValue);
}
FontRenderContext frc = g2.getFontRenderContext();
Rectangle2D tickLabelBounds = tickLabelFont.getStringBounds(tickLabel, frc);
LineMetrics lm = tickLabelFont.getLineMetrics(tickLabel, frc);
float x;
if (edge == RectangleEdge.LEFT) {
x = (float) (cursor
- tickLabelBounds.getWidth() - getTickLabelInsets().right);
}
else {
x = (float) (cursor + getTickLabelInsets().left);
}
float y = (float) (yy + (lm.getAscent() / 2));
Tick tick = new Tick(new Double(currentTickValue), tickLabel, x, y);
getTicks().add(tick);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -