我有一个swing应用程序,其中包含几个包含自定义样式的JavaFX AreaCharts(使用javafx.embed.swing.JFXPanel) . 我们使用了jre 8u20和jre 8u25并且一切正常,现在我不得不更新到jre 8u66并且我的图表看起来不同 .
这个问题与我的情况相反:How to add negative values to JavaFx Area Chart? . 我已经使用图表系列根据数据为图表的背景着色(例如,我需要在红色背景中为没有数据的X轴间隔着色) . JavaFX 8u20区域图表背景被着色到图表线的下限,更新区域图表仅填充背景,忽略轴下方或上方的轴 .
现在,JavaFX区域图表的工作方式与文档中描述的相同:
我如何使用jre 8u66返回javaFX区域图表的旧行为以获得类似的东西:
编辑:
所以我找到了修正负值背景填充的提交http://hg.openjdk.java.net/openjfx/8u60/rt/rev/a57b8ba039d0?revcount=480 .
它只是方法中的几行,我的第一个想法是快速修复:在我自己的类中覆盖这一个方法,但是我遇到了问题,JavaFX类对这些修改不友好许多必需的字段和方法私人或包私人:(
这是我试图改变AreaChart行为的类:
public class NegativeBGAreaChart<X,Y> extends AreaChart<X, Y> {
public NegativeBGAreaChart(@NamedArg("xAxis") Axis<X> xAxis, @NamedArg("yAxis") Axis<Y> yAxis) {
this(xAxis,yAxis, FXCollections.<Series<X,Y>>observableArrayList());
}
public NegativeBGAreaChart(@NamedArg("xAxis") Axis<X> xAxis, @NamedArg("yAxis") Axis<Y> yAxis, @NamedArg("data") ObservableList<Series<X,Y>> data) {
super(xAxis,yAxis, data);
}
@Override
protected void layoutPlotChildren() {
List<LineTo> constructedPath = new ArrayList<>(getDataSize());
for (int seriesIndex=0; seriesIndex < getDataSize(); seriesIndex++) {
Series<X, Y> series = getData().get(seriesIndex);
DoubleProperty seriesYAnimMultiplier = seriesYMultiplierMap.get(series);
double lastX = 0;
final ObservableList<Node> children = ((Group) series.getNode()).getChildren();
ObservableList<PathElement> seriesLine = ((Path) children.get(1)).getElements();
ObservableList<PathElement> fillPath = ((Path) children.get(0)).getElements();
seriesLine.clear();
fillPath.clear();
constructedPath.clear();
for (Iterator<Data<X, Y>> it = getDisplayedDataIterator(series); it.hasNext(); ) {
Data<X, Y> item = it.next();
double x = getXAxis().getDisplayPosition(item.getCurrentX());
double y = getYAxis().getDisplayPosition( getYAxis().toRealValue(getYAxis().toNumericValue(item.getCurrentY()) * seriesYAnimMultiplier.getValue()));
constructedPath.add(new LineTo(x, y));
if (Double.isNaN(x) || Double.isNaN(y)) {
continue;
}
lastX = x;
Node symbol = item.getNode();
if (symbol != null) {
final double w = symbol.prefWidth(-1);
final double h = symbol.prefHeight(-1);
symbol.resizeRelocate(x-(w/2), y-(h/2),w,h);
}
}
if (!constructedPath.isEmpty()) {
Collections.sort(constructedPath, (e1, e2) -> Double.compare(e1.getX(), e2.getX()));
LineTo first = constructedPath.get(0);
final double displayYPos = first.getY();
final double numericYPos = getYAxis().toNumericValue(getYAxis().getValueForDisplay(displayYPos));
// RT-34626: We can't always use getZeroPosition(), as it may be the case
// that the zero position of the y-axis is not visible on the chart. In these
// cases, we need to use the height between the point and the y-axis line.
final double yAxisZeroPos = getYAxis().getZeroPosition();
final boolean isYAxisZeroPosVisible = !Double.isNaN(yAxisZeroPos);
final double yAxisHeight = getYAxis().getHeight();
final double yFillPos = isYAxisZeroPosVisible ? yAxisZeroPos : numericYPos < 0 ? numericYPos - yAxisHeight : yAxisHeight;
seriesLine.add(new MoveTo(first.getX(), displayYPos));
fillPath.add(new MoveTo(first.getX(), yFillPos));
seriesLine.addAll(constructedPath);
fillPath.addAll(constructedPath);
fillPath.add(new LineTo(lastX, yFillPos));
fillPath.add(new ClosePath());
}
}
}
}
问题是:
- 原始AreaChart的字段是私有且无法访问的
private Map,DoubleProperty> seriesYMultiplierMap = new HashMap <>();
- 例如,某些方法是package-private
javafx.scene.chart.XYChart.Data.getCurrentX()
javafx.scene.chart.XYChart.Data.getCurrentY()
javafx.scene.chart.XYChart.getDataSize()
1 回答
尽可能的解决方法我已经做到了:
我知道它有问题,但我现在别无选择,我希望有一天JavaFX会被改变为对外部变化更友好 .
编辑:
这个解决方法是解决所描述的问题,但似乎由于标记为FIXME的代码,系列点出现在错误的坐标上 . 在下面的屏幕截图中,系列的点有Y坐标3或-3,但它们都放在坐标为0的轴上 .
EDIT2:
所以我设法修复它,动画有问题,所以我禁用了动画图表:
并修复了方法(在第二个FIXME行中删除了动画乘数)所以最后我有这个:
修复后所有内容都应该看起来(与上一张图片相同的数据集):