【发布时间】:2015-11-13 14:30:14
【问题描述】:
我有一个摆动应用程序,它的面板包含几个具有自定义样式的 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 面积图的工作方式与文档中描述的一样:
如何返回 javaFX 区域图表的旧行为以使用 jre 8u66 获得类似的东西:
编辑:
所以我找到了修复负值背景填充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 的字段是私有且不可访问的
私有映射,DoubleProperty> seriesYMultiplierMap = new HashMap();
-
有些方法是包私有的,例如
javafx.scene.chart.XYChart.Data.getCurrentX()
javafx.scene.chart.XYChart.Data.getCurrentY()
javafx.scene.chart.XYChart.getDataSize()
【问题讨论】:
-
您面临的问题很可能是由于最近对 JDK 所做的修复 - Area Chart with negative values。只需删除您对图表所做的任何自定义着色,检查输出。如果它仍然不是你想要的,你将不得不重新编写它。如果您仍然无法解决它,请编辑您的问题以向我们展示一些代码(或 css)。