为什么与基于摆动的图表相比,基于Javafx的图表占用更多的内存 [英] Why javafx based charts take more memory as compared to swing based charts

查看:78
本文介绍了为什么与基于摆动的图表相比,基于Javafx的图表占用更多的内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

CandleStick图表是使用JavaFx(使用CSS并扩展XYChart并使用Region和line创建烛台)和JFree图表库开发的.

CandleStick charts have been developed both using JavaFx(using CSS and extending XYChart and creating candle using Region and line) and JFree charting library.

但是Jfree(400 Mb)中的内存使用量很少映射到javafx(2.5Gb). (使用JConsole都运行了2个小时后才获取数据)

But memory usage in Jfree(400 Mb) is far less comapred to javafx(2.5Gb). (Data is taken after runing both for 2 hours using JConsole)

AdvCandleStickChartSample

AdvCandleStickChartSample

/**
 * Copyright (c) 2008, 2012 Oracle and/or its affiliates.
 * All rights reserved. Use is subject to license terms.
 */
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.UUID;

import javafx.animation.Animation;
import javafx.animation.FadeTransition;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.chart.Axis;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.util.Duration;
import java.util.*;

/**
 * A custom candlestick chart.
 * 
 * @see javafx.scene.chart.Axis
 * @see javafx.scene.chart.Chart
 * @see javafx.scene.chart.NumberAxis
 * @see javafx.scene.chart.XYChart
 */
@SuppressWarnings("unused")
public class AdvCandleStickChartSample extends Application {

    // DAY, OPEN, CLOSE, HIGH, LOW, AVERAGE
    private static double[][] data = new double[][] {
        { 1, 25, 20, 32, 16, 20 }, { 2, 26, 30, 33, 22, 25 },
        { 3, 30, 38, 40, 20, 32 }, { 4, 24, 30, 34, 22, 30 },
        { 5, 26, 36, 40, 24, 32 }, { 6, 28, 38, 45, 25, 34 },
        { 7, 36, 30, 44, 28, 39 }, { 8, 30, 18, 36, 16, 31 },
        { 9, 40, 50, 52, 36, 41 }, { 10, 30, 34, 38, 28, 36 }
        };

    private static double[][] data1 = new double[][] {
            { 1, 25, 20, 32, 16, 20 }, { 2, 26, 30, 33, 22, 25 },
            { 3, 30, 38, 40, 20, 32 }, { 4, 24, 30, 34, 22, 30 },
            { 5, 26, 36, 40, 24, 32 }, { 6, 28, 38, 45, 25, 34 },
            { 7, 36, 30, 44, 28, 39 }, { 8, 30, 18, 36, 16, 31 },
            { 9, 40, 50, 52, 36, 41 }, { 10, 30, 34, 38, 28, 36 },
            {11, 24, 12, 30, 8, 32.4},
            {12, 28, 40, 46, 25, 31.6},
            {13, 28, 18, 36, 14, 32.6},
            {14, 38, 30, 40, 26, 30.6},
            {15, 28, 33, 40, 28, 30.6},
            {16, 25, 10, 32, 6, 30.1},
            {17, 26, 30, 42, 18, 27.3},
            {18, 20, 18, 30, 10, 21.9},
            {19, 20, 10, 30, 5, 21.9},
            {20, 26, 16, 32, 10, 17.9},
            {21, 38, 40, 44, 32, 18.9},
            {22, 26, 40, 41, 12, 18.9},
            {23, 30, 18, 34, 10, 18.9},
            {24, 12, 23, 26, 12, 18.2},
            {25, 30, 40, 45, 16, 18.9},
            {26, 25, 35, 38, 20, 21.4},
            {27, 24, 12, 30, 8, 19.6},
            {28, 23, 44, 46, 15, 22.2},
            {29, 28, 18, 30, 12, 23},
            {30, 28, 18, 30, 12, 23.2},
            {31, 28, 18, 30, 12, 22}
            };

    private Timeline animation;
    XYChart.Series<String, Number> series1 = new XYChart.Series<String, Number>();
    int iii=11;
    private void init(Stage primaryStage) {
        Group root = new Group();
        primaryStage.setScene(new Scene(root,500,500,Color.GRAY));
        primaryStage
                .getScene()
                .getStylesheets()
                .add(AdvCandleStickChartSample.class.getResource(
                        "ensemble2.css").toExternalForm());
        final CandleStickChart cd=createChart();
         //Button adddata = new Button("Add Data");
          //  adddata.setOnAction(new EventHandler<ActionEvent>() {
             // @Override
             // public void handle(ActionEvent event) {
                  Timeline oneSecondsWonder = new Timeline(new KeyFrame(Duration.millis(100), new EventHandler<ActionEvent>() {

                        @Override
                        public void handle(ActionEvent event) {
                            getdatatoload(cd);
                            //System.out.println("this is called every 5 seconds on UI thread");
                        }
                    }));
                    oneSecondsWonder.setCycleCount(Timeline.INDEFINITE);
                    oneSecondsWonder.play();
             // }
            //});
        root.getChildren().addAll(cd);
    }

    public void getdatatoload(CandleStickChart cd) {
        Random rn=new Random();
        int ran_ind=rn.nextInt(31);

        double[] day=data1[ran_ind];
        SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
        Date date = new Date();
        //for (int i = 0; i <= 10; i += 1) {
            date.setTime(date.getTime() );
            //System.out.println(dateFormat.format(date));
            series1.getData().add(new XYChart.Data<String,Number>(dateFormat.format(date), day[1],new CandleStickExtraValues(day[2],day[3],day[4],day[5])));
    //  }

        //System.out.println("here");
        //series1.getData().add(new XYChart.Data<String, Number>("iii++",day[1],new CandleStickExtraValues(day[2],day[3],day[4],day[5])));
        /*int j=series1.getData().size();
        System.out.println(j);
        Data item = series1.getData().get(j-1);
        cd.dataItemAdded(series1, j, item);
        //cd.getData().add(series1);*/

    }

    @SuppressWarnings("unchecked")
    protected CandleStickChart createChart() {
        final CategoryAxis xAxis = new CategoryAxis();
        //xAxis.setMinorTickCount(0);
        final NumberAxis yAxis = new NumberAxis();
        final CandleStickChart bc = new CandleStickChart(xAxis, yAxis);
        // setup chart
        bc.setTitle("Custom Candle Stick Chart");
        xAxis.setLabel("Day");
        yAxis.setLabel("Price");
        // add starting data
    //XYChart.Series<Number, Number> series = new XYChart.Series<Number, Number>();
        /*
         * Random ran=new Random(); data=new double[100][6]; for(int
         * i=0;i<100;i++) { data[i][0]= i; data[i][1]= ran.nextInt(40) + 1;
         * data[i][2]= ran.nextInt(40) + 1; data[i][3]= ran.nextInt(40) + 20;
         * data[i][4]= ran.nextInt(20) + 10; data[i][5]= (data[i][3] +
         * data[i][4])/2; } for (int i=0; i< 100; i++) { double[] day; day=new
         * double[6]; day[0]=ran.nextInt(40)+1; day[1]=ran.nextInt(40)+1;
         * day[2]=ran.nextInt(40)+1; day[3]=ran.nextInt(40)+1;
         * day[4]=ran.nextInt(40)+1; day[5]=ran.nextInt(40)+1;
         * series.getData().add( new
         * XYChart.Data<Number,Number>(day[0],day[1],new
         * CandleStickExtraValues(day[2],day[3],day[4],day[5])) ); }
         */
        for (int i = 0; i < data.length; i++) {
            double[] day = data[i];
            /*series1.getData().add(
                    new XYChart.Data<String, Number>("day[0]", day[1],
                            new CandleStickExtraValues(day[2], day[3], day[4],
                                    day[5])));*/
        }
        ObservableList<XYChart.Series<String, Number>> data = bc.getData();
        if (data == null) {
            data = FXCollections.observableArrayList(series1);
            bc.setData(data);
        } else {
            bc.getData().add(series1);
        }
        return bc;
    }

    /**
     * A candlestick chart is a style of bar-chart used primarily to describe
     * price movements of a security, derivative, or currency over time.
     * 
     * The Data Y value is used for the opening price and then the close, high
     * and low values are stored in the Data's extra value property using a
     * CandleStickExtraValues object.
     */
    private class CandleStickChart extends XYChart<String, Number> {

        // -------------- CONSTRUCTORS
        // ----------------------------------------------
        /**
         * Construct a new CandleStickChart with the givextraValuePropertyen
         * axis.
         * 
         * @param xAxis
         *            The x axis to use
         * @param yAxis
         *            The y axis to use
         */
        public CandleStickChart(Axis<String> xAxis, Axis<Number> yAxis) {
            super(xAxis, yAxis);
            setAnimated(false);
            xAxis.setAnimated(false);
            yAxis.setAnimated(false);
        }

        /**
         * Construct a new CandleStickChart with the given axis and data.
         * 
         * @param xAxis
         *            The x axis to use
         * @param yAxis
         *            The y axis to use
         * @param data
         *            The data to use, this is the actual list used so any
         *            changes to it will be reflected in the chart
         */

        public CandleStickChart(Axis<String> xAxis, Axis<Number> yAxis,
                ObservableList<Series<String, Number>> data) {
            this(xAxis, yAxis);
            setUserData(data);
        }

        // -------------- METHODS
        // ------------------------------------------------------------------------------------------
        /** Called to update and layout the content for the plot */
        @Override
        protected void layoutPlotChildren() {
            // we have nothing to layout if no data is present
            if (getData() == null) {
                return;
            }
            // update candle positions
            for (int seriesIndex = 0; seriesIndex < getData().size(); seriesIndex++) {
                Series<String, Number> series = getData().get(seriesIndex);
                Iterator<Data<String, Number>> iter = getDisplayedDataIterator(series);
                Path seriesPath = null;
                if (series.getNode() instanceof Path) {
                    seriesPath = (Path) series.getNode();
                    seriesPath.getElements().clear();
                }
                while (iter.hasNext()) {
                    Data<String, Number> item = iter.next();
                    double x = getXAxis().getDisplayPosition(
                            getCurrentDisplayedXValue(item));
                    double y = getYAxis().getDisplayPosition(
                            getCurrentDisplayedYValue(item));
                    Node itemNode = item.getNode();
                    CandleStickExtraValues extra = (CandleStickExtraValues) item
                            .getExtraValue();
                    if (itemNode instanceof Candle && extra != null) {
                        Candle candle = (Candle) itemNode;

                        double close = getYAxis().getDisplayPosition(
                                extra.getClose());
                        double high = getYAxis().getDisplayPosition(
                                extra.getHigh());
                        double low = getYAxis().getDisplayPosition(
                                extra.getLow());
                        // calculate candle width
                        double candleWidth = -1;
                        if (getXAxis() instanceof CategoryAxis) {
                            CategoryAxis xa = (CategoryAxis) getXAxis();
                        //****//candleWidth = xa.getDisplayPosition(xa.getTickLength()) * 0.90; // use 90% width
                                                            // between ticks
                        }
                        // update candle
                        // System.out.format("x = %f y=%f%n",x,y);
                        candle.update(close - y, high - y, low - y, candleWidth);
                        candle.updateTooltip(item.getYValue().doubleValue(),
                                extra.getClose(), extra.getHigh(),
                                extra.getLow());

                        // position the candle
                        candle.setLayoutX(x);
                        candle.setLayoutY(y);
                    }
                    if (seriesPath != null) {
                        if (seriesPath.getElements().isEmpty()) {
                            seriesPath.getElements().add(
                                    new MoveTo(x, getYAxis()
                                            .getDisplayPosition(
                                                    extra.getAverage())));
                        } else {
                            seriesPath.getElements().add(
                                    new LineTo(x, getYAxis()
                                            .getDisplayPosition(
                                                    extra.getAverage())));
                        }
                    }
                }
            }
        }

        @Override
        protected void dataItemChanged(Data<String, Number> item) {
        }

        @Override
        protected void dataItemAdded(Series<String, Number> series,
                int itemIndex, Data<String, Number> item) {
            //System.out.println("DatItemAdded");
            Node candle = createCandle(getData().indexOf(series), item,
                    itemIndex);
            if (shouldAnimate()) {
                candle.setOpacity(0);
                getPlotChildren().add(candle);
                // fade in new candle
                FadeTransition ft = new FadeTransition(Duration.millis(500),
                        candle);
                ft.setToValue(1);
                ft.play();
            } else {
                getPlotChildren().add(candle);
            }
            // always draw average line on top
            /*if (series.getNode() != null) {
                series.getNode().toFront();
            }*/
        }

        @Override
        protected void dataItemRemoved(Data<String, Number> item,
                Series<String, Number> series) {

            final Node candle = item.getNode();
            if (shouldAnimate()) {
                // fade out old candle
                FadeTransition ft = new FadeTransition(Duration.millis(500),
                        candle);
                ft.setToValue(0);
                ft.setOnFinished(new EventHandler<ActionEvent>() {

                    @Override
                    public void handle(ActionEvent actionEvent) {
                        getPlotChildren().remove(candle);
                    }
                });
                ft.play();
            } else {
                getPlotChildren().remove(candle);
            }
        }

        @SuppressWarnings("rawtypes")
        @Override
        protected void seriesAdded(Series<String, Number> series,
                int seriesIndex) {
//          System.out.println("seriesAdded");
            //System.out.println(seriesIndex);
            // called once from setData() function (internal to XYchart) from
            // createChart
            // handle any data already in series

            for (int j = 0; j < series.getData().size(); j++) {
                Data item = series.getData().get(j);
                Node candle = createCandle(seriesIndex, item, j);
                if (shouldAnimate()) {
                    candle.setOpacity(0);
                    getPlotChildren().add(candle);
                    // fade in new candle
                    FadeTransition ft = new FadeTransition(
                            Duration.millis(500), candle);
                    ft.setToValue(1);
                    ft.play();
                } else {
                    getPlotChildren().add(candle);
                }
            }
            // create series path
            Path seriesPath = new Path();
            seriesPath.getStyleClass().setAll("candlestick-average-line",
                    "series" + seriesIndex);
            series.setNode(seriesPath);
            getPlotChildren().add(seriesPath);
        }

        @Override
        protected void seriesRemoved(Series<String, Number> series) {
            // remove all candle nodes
            for (XYChart.Data<String, Number> d : series.getData()) {
                final Node candle = d.getNode();
                if (shouldAnimate()) {
                    // fade out old candle
                    FadeTransition ft = new FadeTransition(
                            Duration.millis(500), candle);
                    ft.setToValue(0);
                    ft.setOnFinished(new EventHandler<ActionEvent>() {

                        @Override
                        public void handle(ActionEvent actionEvent) {
                            getPlotChildren().remove(candle);
                        }
                    });
                    ft.play();
                } else {
                    getPlotChildren().remove(candle);
                }
            }
        }

        /**
         * Create a new Candle node to represent a single data item
         * 
         * @param seriesIndex
         *            The index of the series the data item is in
         * @param item
         *            The data item to create node for
         * @param itemIndex
         *            The index of the data item in the series
         * @return New candle node to represent the give data item
         */
        @SuppressWarnings("rawtypes")
        private Node createCandle(int seriesIndex, final Data item,
                int itemIndex) {
            Node candle = item.getNode();
            // check if candle has already been created
            if (candle instanceof Candle) {
                ((Candle) candle).setSeriesAndDataStyleClasses("series"
                        + seriesIndex, "data" + itemIndex);
            } else {
                candle = new Candle("series" + seriesIndex, "data" + itemIndex);
                item.setNode(candle);
            }
            return candle;
        }

        /**
         * This is called when the range has been invalidated and we need to
         * update it. If the axis are auto ranging then we compile a list of all
         * data that the given axis has to plot and call invalidateRange() on
         * the axis passing it that data.
         */
        @Override
        protected void updateAxisRange() {
            // called once :)
            // For candle stick chart we need to override this method as we need
            // to let the axis know that they need to be able
            // to cover the whole area occupied by the high to low range not
            // just its center data value
            final Axis<String> xa = getXAxis();
            final Axis<Number> ya = getYAxis();
            List<String> xData = null;
            List<Number> yData = null;
            if (xa.isAutoRanging()) {
                xData = new ArrayList<String>();
            }
            if (ya.isAutoRanging()) {
                yData = new ArrayList<Number>();
            }
            if (xData != null || yData != null) {
                for (Series<String, Number> series : getData()) {
                    for (Data<String, Number> data : series.getData()) {
                        if (xData != null) {
                        xData.add(data.getXValue());
                        }
                        if (yData != null) {
                            CandleStickExtraValues extras = (CandleStickExtraValues) data
                                    .getExtraValue();
                            if (extras != null) {
                                yData.add(extras.getHigh());
                                yData.add(extras.getLow());
                            } else {
                                yData.add(data.getYValue());
                            }
                        }
                    }
                }
                if (xData != null) {
                    xa.invalidateRange(xData);
                }
                if (yData != null) {
                    ya.invalidateRange(yData);
                }
            }
        }
/*
        @Override
        protected void dataItemAdded(
                javafx.scene.chart.XYChart.Series<String, Number> series,
                int itemIndex,
                javafx.scene.chart.XYChart.Data<String, Number> item) {
            // TODO Auto-generated method stub

        }

        @Override
        protected void dataItemChanged(
                javafx.scene.chart.XYChart.Data<String, Number> item) {
            // TODO Auto-generated method stub

        }

        @Override
        protected void dataItemRemoved(
                javafx.scene.chart.XYChart.Data<String, Number> item,
                javafx.scene.chart.XYChart.Series<String, Number> series) {
            // TODO Auto-generated method stub

        }

        @Override
        protected void seriesAdded(
                javafx.scene.chart.XYChart.Series<String, Number> series,
                int seriesIndex) {
            // TODO Auto-generated method stub

        }

        @Override
        protected void seriesRemoved(
                javafx.scene.chart.XYChart.Series<String, Number> series) {
            // TODO Auto-generated method stub

        }*/
    }

    /** Data extra values for storing close, high and low. */
    private class CandleStickExtraValues {
        private double close;
        private double high;
        private double low;
        private double average;

        public CandleStickExtraValues(double close, double high, double low,
                double average) {
            this.close = close;
            this.high = high;
            this.low = low;
            this.average = average;
        }

        public double getClose() {
            return close;
        }

        public double getHigh() {
            return high;
        }

        public double getLow() {
            return low;
        }

        public double getAverage() {
            return average;
        }
    }

    /** Candle node used for drawing a candle */
    private class Candle extends Group {
        private Line highLowLine = new Line();
        private Region bar = new Region();
        private String seriesStyleClass;
        private String dataStyleClass;
        private boolean openAboveClose = true;
        private Tooltip tooltip = new Tooltip();

        private Candle(String seriesStyleClass, String dataStyleClass) {
            setAutoSizeChildren(false);
            getChildren().addAll(highLowLine, bar);
            this.seriesStyleClass = seriesStyleClass;
            this.dataStyleClass = dataStyleClass;
            updateStyleClasses();
            tooltip.setGraphic(new TooltipContent());
            Tooltip.install(bar, tooltip);
        }

        public void setSeriesAndDataStyleClasses(String seriesStyleClass,
                String dataStyleClass) {
            this.seriesStyleClass = seriesStyleClass;
            this.dataStyleClass = dataStyleClass;
            updateStyleClasses();
        }

        public void update(double closeOffset, double highOffset,
                double lowOffset, double candleWidth) {
            openAboveClose = closeOffset > 0;
            updateStyleClasses();
            highLowLine.setStartY(highOffset);
            highLowLine.setEndY(lowOffset);
            if (candleWidth == -1) {
                candleWidth = bar.prefWidth(-1);
            }
            if (openAboveClose) {
                bar.resizeRelocate(-candleWidth / 2, 0, candleWidth,
                        closeOffset);
            } else {
                bar.resizeRelocate(-candleWidth / 2, closeOffset, candleWidth,
                        closeOffset * -1);
            }
            // System.out.println(bar.localToScene(bar.getBoundsInLocal()));
        }

        public void updateTooltip(double open, double close, double high,
                double low) {
            TooltipContent tooltipContent = (TooltipContent) tooltip
                    .getGraphic();
            tooltipContent.update(open, close, high, low);
            // tooltip.setText("Open: "+open+"\nClose: "+close+"\nHigh: "+high+"\nLow: "+low);
        }

        private void updateStyleClasses() {
            getStyleClass().setAll("candlestick-candle", seriesStyleClass,
                    dataStyleClass);
            highLowLine.getStyleClass().setAll("candlestick-line",
                    seriesStyleClass, dataStyleClass,
                    openAboveClose ? "open-above-close" : "close-above-open");
            bar.getStyleClass().setAll("candlestick-bar", seriesStyleClass,
                    dataStyleClass,
                    openAboveClose ? "open-above-close" : "close-above-open");
        }
    }

    private class TooltipContent extends GridPane {
        private Label openValue = new Label();
        private Label closeValue = new Label();
        private Label highValue = new Label();
        private Label lowValue = new Label();

        private TooltipContent() {
            Label open = new Label("OPEN:");
            Label close = new Label("CLOSE:");
            Label high = new Label("HIGH:");
            Label low = new Label("LOW:");
            open.getStyleClass().add("candlestick-tooltip-label");
            close.getStyleClass().add("candlestick-tooltip-label");
            high.getStyleClass().add("candlestick-tooltip-label");
            low.getStyleClass().add("candlestick-tooltip-label");
            setConstraints(open, 0, 0);
            setConstraints(openValue, 1, 0);
            setConstraints(close, 0, 1);
            setConstraints(closeValue, 1, 1);
            setConstraints(high, 0, 2);
            setConstraints(highValue, 1, 2);
            setConstraints(low, 0, 3);
            setConstraints(lowValue, 1, 3);
            getChildren().addAll(open, openValue, close, closeValue, high,
                    highValue, low, lowValue);
        }

        public void update(double open, double close, double high, double low) {
            openValue.setText(Double.toString(open));
            closeValue.setText(Double.toString(close));
            highValue.setText(Double.toString(high));
            lowValue.setText(Double.toString(low));
        }
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        init(primaryStage);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

ensemble2.css

ensemble2.css

/*
 * Copyright (c) 2008, 2012 Oracle and/or its affiliates.
 * All rights reserved. Use is subject to license terms.
 *
 * This file is available and licensed under the following license:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  - Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the distribution.
 *  - Neither the name of Oracle Corporation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 /*
/* ====== CANDLE STICK CHART =========================================================== */

.candlestick-tooltip-label {
    -fx-font-size: 0.75em;
    -fx-font-weight: bold;
    -fx-text-fill: #666666;
    -fx-padding: 2 5 2 0;
}
.candlestick-average-line {
    -fx-stroke: #106ece;
    -fx-stroke-width: 2px;
}
.candlestick-candle {
    -fx-effect: dropshadow( two-pass-box , rgba(0,0,0,0.4) , 10, 0.0 , 2 , 4 );
}
.candlestick-line {
    -fx-stroke: #666666;
    -fx-stroke-width: 3px;
}
.candlestick-bar {
    -fx-padding: 5;
    -demo-bar-fill: red;
    -fx-background-color: linear-gradient(derive(-demo-bar-fill,-30%), derive(-demo-bar-fill,-40%)),
                          linear-gradient(derive(-demo-bar-fill,100%), derive(-demo-bar-fill, 10%)),
                          linear-gradient(derive(-demo-bar-fill,30%), derive(-demo-bar-fill,-10%));
    -fx-background-insets: 0,1,2;
}
.candlestick-bar.close-above-open {
    -demo-bar-fill: #95ce1b;
}
.candlestick-bar.open-above-close {
    -demo-bar-fill: #ce2700;
}

推荐答案

1)JavaFX图表将始终比JFreeChart消耗更多的内存,因为图表上的节点是场景图的活动部分.也就是说,散点图中的每个点都是一个节点,可以对输入事件做出反应,执行自定义渲染,执行动画甚至播放视频文件.另一方面,JFreeChart静态地绘制图表.一个或另一个对您的应用程序是否有利取决于用例,但是JavaFX方法肯定会使用更多的内存.

1) JavaFX charts will always consume quite a bit more memory than JFreeChart because the nodes on the charts are active parts of the scene graph. That is, every dot in a scatter chart is a node that can react to input events, do custom rendering, perform an animation or even play a video file. JFreeChart, on the other hand, renders the charts statically. Whether one or the other is beneficial to your application depends on the use case, but the JavaFX approach definitely uses more memory.

2)看来,JavaFX中当前对CSS的处理仍可以使用一些优化.我仅根据经验发表此声明,但至少在我所有的测试中,开销都是一致的.

2) It appears that the current handling of CSS in JavaFX could still use some optimization. I am basing this statement solely on experience, but at least for all my tests the overhead there was a consistent overhead.

3)话虽如此,2.5GB和400MB似乎太多了.您可以使用FX图表代码发布一个小型测试示例吗?可能还有其他与JavaFX不相关的东西.

3) All that being said, 2.5GB vs. 400MB seems to be way too much. Could you post a small test example with your FX charting code? There may be other stuff going that is not related to JavaFX.

这篇关于为什么与基于摆动的图表相比,基于Javafx的图表占用更多的内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆