Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaFX面积图行为已更改_Java_Javafx_Javafx 8 - Fatal编程技术网

JavaFX面积图行为已更改

JavaFX面积图行为已更改,java,javafx,javafx-8,Java,Javafx,Javafx 8,我有一个swing应用程序,它的面板包含几个自定义样式的JavaFXAreacharts(使用JavaFX.embed.swing.JFXPanel)。我们曾经使用过jre 8u20和jre 8u25,它们都工作得很好,现在我不得不更新到jre 8u66,我的图表看起来不同了 这个问题与我的情况相反:。我已经使用图表系列根据数据为图表的背景上色(例如,我需要为缺少数据的X轴间隔上色为红色背景)。JavaFX 8u20面积图背景被着色到图表线的下限,在更新面积图填充背景后,仅将其添加到轴,忽略轴下

我有一个swing应用程序,它的面板包含几个自定义样式的JavaFXAreacharts(使用JavaFX.embed.swing.JFXPanel)。我们曾经使用过jre 8u20和jre 8u25,它们都工作得很好,现在我不得不更新到jre 8u66,我的图表看起来不同了

这个问题与我的情况相反:。我已经使用图表系列根据数据为图表的背景上色(例如,我需要为缺少数据的X轴间隔上色为红色背景)。JavaFX 8u20面积图背景被着色到图表线的下限,在更新面积图填充背景后,仅将其添加到轴,忽略轴下方或上方的部分

现在,JavaFX面积图的工作原理如文档中所述:

如何使用jre 8u66将javaFX面积图返回到旧行为以获得类似结果:

编辑:

所以我找到了commit,它修复了负值background fill

方法中只有几行,我的第一个想法是快速修复:在我自己的类中重写这一个方法,但我在这样做时遇到了问题,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());
            }
        }
    }
}
public class NegativeBGAreaChart扩展面积图{
公共负片加莱哈特(@NamedArg(“xAxis”)轴xAxis,@NamedArg(“yAxis”)轴yAxis){
这是(xAxis、yAxis、FXCollections.observearraylist());
}
公共负片图表(@NamedArg(“xAxis”)轴xAxis,@NamedArg(“yAxis”)轴yAxis,@NamedArg(“数据”)可观察列表数据){
super(xAxis、yAxis、data);
}
@凌驾
受保护的无效layoutPlotChildren(){
List constructedPath=newarraylist(getDataSize());
对于(int seriesIndex=0;seriesIndexDouble.compare(e1.getX(),e2.getX());
LineTo first=constructedPath.get(0);
final double displayPOS=first.getY();
最终的双精度数值ypos=getYAxis().toNumericValue(getYAxis().getValueForDisplay(displayYPos));
//RT-34626:我们不能总是使用getZeroPosition(),因为可能是这样
//y轴的零位在图表上不可见。在这些
//在这种情况下,我们需要使用点和y轴线之间的高度。
最终双yAxisZeroPos=getYAxis().getZeroPosition();
最终布尔值isYAxisZeroPosVisible=!Double.isNaN(yAxisZeroPos);
最终双yAxisHeight=getYAxis().getHeight();
最终双yFillPos=isYAxisZeroPosVisible?yAxisZeroPos:numericYPos<0?numericYPos-yAxisHeight:yAxisHeight;
add(newmoveto(first.getX(),displayPos));
add(newmoveto(first.getX(),yFillPos));
seriesLine.addAll(constructedPath);
addAll(constructedPath);
添加(新行到(lastX,yFillPos));
add(newclosepath());
}
}
}
}
问题是:

  • 原始区域图的字段是私有的且不可访问

    私有映射,DoubleProperty>seriesYMultiplierMap=newhashmap()

  • 例如,有些方法是包私有的

    javafx.scene.chart.XYChart.Data.getCurrentX()

    javafx.scene.chart.XYChart.Data.getCurrentY()

    javafx.scene.chart.XYChart.getDataSize()


  • 因此,我尽可能地解决了这个问题:

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    import javafx.beans.NamedArg;
    import javafx.beans.property.DoubleProperty;
    import javafx.beans.property.SimpleDoubleProperty;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.scene.Group;
    import javafx.scene.Node;
    import javafx.scene.chart.AreaChart;
    import javafx.scene.chart.Axis;
    import javafx.scene.shape.ClosePath;
    import javafx.scene.shape.LineTo;
    import javafx.scene.shape.MoveTo;
    import javafx.scene.shape.Path;
    import javafx.scene.shape.PathElement;
    
    /**
     * AreaChart - Plots the area between the line that connects the data points     and
     * the 0 line on the Y axis. This implementation Plots the area between the line
     * that connects the data points and the bottom of the chart area.
     * 
     * @since JavaFX 2.0
     */
    public class NegativeBGAreaChart<X, Y> extends AreaChart<X, Y> {
        protected Map<Series<X, Y>, DoubleProperty> shadowSeriesYMultiplierMap = new HashMap<>();
    
        // -------------- CONSTRUCTORS ----------------------------------------------
    
        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);
        }
    
        // -------------- METHODS ------------------------------------------------------------------------------------------
        @Override
        protected void seriesAdded(Series<X, Y> series, int seriesIndex) {
            DoubleProperty seriesYAnimMultiplier = new SimpleDoubleProperty(this, "seriesYMultiplier");
            shadowSeriesYMultiplierMap.put(series, seriesYAnimMultiplier);
            super.seriesAdded(series, seriesIndex);
        }
    
        @Override
        protected void seriesRemoved(final Series<X, Y> series) {
            shadowSeriesYMultiplierMap.remove(series);
            super.seriesRemoved(series);
        }
    
        @Override
        protected void layoutPlotChildren() {
            // super.layoutPlotChildren();
            try {
                List<LineTo> constructedPath = new ArrayList<>(getDataSize());
                for (int seriesIndex = 0; seriesIndex < getDataSize(); seriesIndex++) {
                    Series<X, Y> series = getData().get(seriesIndex);
                    DoubleProperty seriesYAnimMultiplier = shadowSeriesYMultiplierMap.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.getXValue());// FIXME: here should be used item.getCurrentX()
                        double y = getYAxis().getDisplayPosition(
                            getYAxis().toRealValue(
                                    getYAxis().toNumericValue(item.getYValue()) * seriesYAnimMultiplier.getValue()));// FIXME: here should be used item.getCurrentY()
                        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);
    
                        seriesLine.add(new MoveTo(first.getX(), first.getY()));
                        fillPath.add(new MoveTo(first.getX(), getYAxis().getHeight()));
    
                        seriesLine.addAll(constructedPath);
                        fillPath.addAll(constructedPath);
                        fillPath.add(new LineTo(lastX, getYAxis().getHeight()));
                        fillPath.add(new ClosePath());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Gets the size of the data returning 0 if the data is null
         *
         * @return The number of items in data, or null if data is null
         */
        public int getDataSize() {
            final ObservableList<Series<X, Y>> data = getData();
            return (data != null) ? data.size() : 0;
        }
    }
    
    并修复了该方法(在第二个修复行中删除了动画倍增器),因此最后我有了以下内容:

    public class NegativeBGAreaChart<X, Y> extends AreaChart<X, Y> {
        protected Map<Series<X, Y>, DoubleProperty> shadowSeriesYMultiplierMap = new HashMap<>();
    
        // -------------- CONSTRUCTORS ----------------------------------------------
    
        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);
        }
    
        // -------------- METHODS ------------------------------------------------------------------------------------------
        @Override
        protected void seriesAdded(Series<X, Y> series, int seriesIndex) {
            DoubleProperty seriesYAnimMultiplier = new SimpleDoubleProperty(this, "seriesYMultiplier");
            shadowSeriesYMultiplierMap.put(series, seriesYAnimMultiplier);
            super.seriesAdded(series, seriesIndex);
        }
    
        @Override
        protected void seriesRemoved(final Series<X, Y> series) {
            shadowSeriesYMultiplierMap.remove(series);
            super.seriesRemoved(series);
        }
    
        @Override
        protected void layoutPlotChildren() {
    //          super.layoutPlotChildren();
            try {
                List<LineTo> constructedPath = new ArrayList<>(getDataSize());
                for (int seriesIndex = 0; seriesIndex < getDataSize(); seriesIndex++) {
                    Series<X, Y> series = getData().get(seriesIndex);
                    DoubleProperty seriesYAnimMultiplier = shadowSeriesYMultiplierMap.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.getXValue());// FIXME: here should be used item.getCurrentX()
                        double y = getYAxis().getDisplayPosition(getYAxis().toRealValue(getYAxis().toNumericValue(item.getYValue())));// FIXME: here should be used item.getCurrentY()
                        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);
    
                        seriesLine.add(new MoveTo(first.getX(), first.getY()));
                        fillPath.add(new MoveTo(first.getX(), getYAxis().getHeight()));
    
                        seriesLine.addAll(constructedPath);
                        fillPath.addAll(constructedPath);
                        fillPath.add(new LineTo(lastX, getYAxis().getHeight()));
                        fillPath.add(new ClosePath());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Gets the size of the data returning 0 if the data is null
         *
         * @return The number of items in data, or null if data is null
         */
        public int getDataSize() {
            final ObservableList<Series<X, Y>> data = getData();
            return (data != null) ? data.size() : 0;
        }
    }
    
    public class NegativeBGAreaChart扩展面积图{
    受保护映射shadowSeriesYMultiplierMap=new HashMap();
    //-------构造函数----------------------------------------------
    公共负片加莱哈特(@NamedArg(“xAxis”)轴xAxis,@NamedArg(“yAxis”)轴yAxis){
    这是(xAxis、yAxis、FXCollections.observearraylist());
    }
    公共负片图表(@NamedArg(“xAxis”)轴xAxis,@NamedArg(“yAxis”)轴yAxis,@NamedArg(“数据”)可观察列表数据){
    super(xAxis、yAxis、data);
    }
    //-------方法------------------------------------------------------------------------------------------
    @凌驾
    添加受保护的无效系列(系列、内部系列索引){
    双重正体
    
    public class NegativeBGAreaChart<X, Y> extends AreaChart<X, Y> {
        protected Map<Series<X, Y>, DoubleProperty> shadowSeriesYMultiplierMap = new HashMap<>();
    
        // -------------- CONSTRUCTORS ----------------------------------------------
    
        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);
        }
    
        // -------------- METHODS ------------------------------------------------------------------------------------------
        @Override
        protected void seriesAdded(Series<X, Y> series, int seriesIndex) {
            DoubleProperty seriesYAnimMultiplier = new SimpleDoubleProperty(this, "seriesYMultiplier");
            shadowSeriesYMultiplierMap.put(series, seriesYAnimMultiplier);
            super.seriesAdded(series, seriesIndex);
        }
    
        @Override
        protected void seriesRemoved(final Series<X, Y> series) {
            shadowSeriesYMultiplierMap.remove(series);
            super.seriesRemoved(series);
        }
    
        @Override
        protected void layoutPlotChildren() {
    //          super.layoutPlotChildren();
            try {
                List<LineTo> constructedPath = new ArrayList<>(getDataSize());
                for (int seriesIndex = 0; seriesIndex < getDataSize(); seriesIndex++) {
                    Series<X, Y> series = getData().get(seriesIndex);
                    DoubleProperty seriesYAnimMultiplier = shadowSeriesYMultiplierMap.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.getXValue());// FIXME: here should be used item.getCurrentX()
                        double y = getYAxis().getDisplayPosition(getYAxis().toRealValue(getYAxis().toNumericValue(item.getYValue())));// FIXME: here should be used item.getCurrentY()
                        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);
    
                        seriesLine.add(new MoveTo(first.getX(), first.getY()));
                        fillPath.add(new MoveTo(first.getX(), getYAxis().getHeight()));
    
                        seriesLine.addAll(constructedPath);
                        fillPath.addAll(constructedPath);
                        fillPath.add(new LineTo(lastX, getYAxis().getHeight()));
                        fillPath.add(new ClosePath());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Gets the size of the data returning 0 if the data is null
         *
         * @return The number of items in data, or null if data is null
         */
        public int getDataSize() {
            final ObservableList<Series<X, Y>> data = getData();
            return (data != null) ? data.size() : 0;
        }
    }