正如您所看到的,当范围轴跨越大面积并且刻度标签太靠近时,它们开始重叠。我想实现某种逻辑来检测它们是否重叠,如果是,只显示一个首选(或适合的数量)。但是,我有点不确定如何实现这一目标。
逻辑将是这样的:
但是有哪些方法可以做到这一点?从我买的API文档中我找到了这个方法
public double valueToJava2D(double value, Rectangle2D area, RectangleEdge edge);
但是我需要提供这个功能的区域和边缘是什么?如果是一个勾选标签,我怎么能得到宽度和高度?这是正确的方法吗,还是有更好的方法可以带来成功?
答案 0 :(得分:0)
我在JFree论坛上发布了这个问题(找到了trashgod)并得到了一些不错的提示there。我在那里发布的最终代码解决了我的问题如下:
@SuppressWarnings({"RawUseOfParameterizedType", "serial"})
private static class CustomTickMarkNumberAxis extends NumberAxis {
private double[] customTicksSortedOnImportance;
/**
* A list ticks sorted after importance. In case of overlapping,
* a higher ranked tick will trump a lower ranked tick, thus <i>not showing</i>
* the lower ranked (overlapping) tick.
* Other lower ranked ticks might still be shown, if they are not overlapping
*/
public CustomTickMarkNumberAxis(double[] customTicksSortedOnImportance) {
this.customTicksSortedOnImportance = customTicksSortedOnImportance;
}
protected List<NumberTick> refreshTicksVertical(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge) {
List<NumberTick> result = new java.util.ArrayList<NumberTick>();
//(... snip ...)
Area tickLabelArea = new Area(); /** Used for overlap detection */
for (int i = 0; i < customTicksSortedOnImportance.length; i++) {
// The next lines of code are different from NumberAxis
double currentTickValue = customTicksSortedOnImportance[i];
currentTickValue = NumberUtil.round(currentTickValue, precision);
//(... snip ...)
/* Overlapping logic here */
NumberTick numberTick = new NumberTick(currentTickValue, tickLabel, anchor, rotationAnchor, angle);
Rectangle2D labelBounds = getTickBounds(numberTick, g2);
double java2dValue = valueToJava2D(currentTickValue, g2.getClipBounds(), edge);
labelBounds.setRect(labelBounds.getX(), java2dValue, labelBounds.getWidth(), labelBounds.getHeight());
if (!tickLabelIsOverlapping(tickLabelArea, labelBounds)) {
result.add(numberTick);
tickLabelArea.add(new Area(labelBounds));
}
//(... snip ...)
}
return result;
}
private boolean tickLabelIsOverlapping(Area area, Rectangle2D rectangle) {
return area.intersects(rectangle);
}
private Rectangle2D getTickBounds(NumberTick numberTick, Graphics2D g2) {
FontMetrics fm = g2.getFontMetrics(getTickLabelFont());
return TextUtilities.getTextBounds(numberTick.getText(), g2, fm);
}
}