Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Heavy performance loss using CrosshairOverlayFX #5

Open
team172011 opened this issue Dec 17, 2017 · 3 comments
Open

Heavy performance loss using CrosshairOverlayFX #5

team172011 opened this issue Dec 17, 2017 · 3 comments

Comments

@team172011
Copy link

team172011 commented Dec 17, 2017

I am happy to see that there is a JavaFX wrapper for JFreeChart!

After moving with my charting application from Swing to JavaFX i discovered that the CrosshairOverlayFX is delayed on my CombinedXYPlot with 750 candlesticks as DefaultHighLowDataset. Adding more data to the chart (XYPlots as sub plots and TimeSeriesCollection data of the same size) makes the cross hair overlay so slow that it cannot be used seriously.
I have enable caching in the ChartCanvas Region but it does not change anything. Are there other possibilities to improve performance of the overlay? In swing the cross hair overlay worked perfectly and very fast with exact the same settings and data

@jfree
Copy link
Owner

jfree commented Dec 30, 2017

In the Swing version (ChartPanel) there is the option to draw the chart to an offscreen buffer (BufferedImage) so if the chart doesn't change, then drawing the overlay just requires copying the chart image to the panel then drawing the overlay - this is quick.

But in the JavaFX version (ChartCanvas) everything is redrawn from scratch (chart first, overlay(s) second). I could implement the same offscreen buffer approach within ChartCanvas, but the Canvas is already buffered, so I'm thinking another approach might be to employ a second Canvas (transparent) to draw the overlay...I didn't try it yet, but I can't think why it wouldn't work.

@team172011
Copy link
Author

Thanks for your answer. I will try to apply your approach and make a PR if it works fine.

@team172011
Copy link
Author

team172011 commented Jan 5, 2018

Maybe it is not a qualified approach for a library, but its simple, fast and independent of the draw() function. I have added an EventHandler to the ChartViewer class that draws a crosshair with help of two JavaFX Lines:

public class TaChartViewer extends Region {

    private TaChartCanvas canvas;

    private final Line xCrosshair; // javaFX objects
    private final Line yCrosshair;
    private final Label xLabel;
    private final Label yLabel;

    // (other code ...)


    public ChartViewer(JFreeChart chart, boolean contextMenuEnabled) {
        // (other code ...)
        this.xCrosshair = new Line(0,0,this.getPrefWidth(),0);
        this.yCrosshair = new Line(0,0,0,this.getPrefHeight());
        this.xCrosshair.setMouseTransparent(true);
        this.yCrosshair.setMouseTransparent(true);
        this.getChildren().add(xCrosshair);
        this.getChildren().add(yCrosshair);
        this.xLabel = new Label("");
        this.yLabel = new Label("");
        this.yLabel.setMouseTransparent(true);
        this.xLabel.setMouseTransparent(true);
        this.getChildren().add(xLabel);
        this.getChildren().add(yLabel);

        this.setOnMouseMoved( e ->{
                final double x = e.getX();
                final double y = e.getY();

                // do some stuff like in the paintOverlay function of CrosshairOverlay
                Rectangle2D dataArea = getCanvas().getRenderingInfo().getPlotInfo().getDataArea();

                if(x > dataArea.getMinX() && y > dataArea.getMinY()
                        && x < dataArea.getMaxX() && y < dataArea.getMaxY()) {
                    setCrosshairVisible(true);
                    XYPlot plot = (XYPlot) getCanvas().getChart().getPlot();

                    org.jfree.chart.axis.ValueAxis xAxis = plot.getDomainAxis();
                    RectangleEdge xAxisEdge = plot.getDomainAxisEdge();

                    xCrosshair.setStartY(dataArea.getMinY());
                    xCrosshair.setStartX(x);
                    xCrosshair.setEndY(dataArea.getMaxY());
                    xCrosshair.setEndX(x);
                    xLabel.setLayoutX(x);
                    xLabel.setLayoutY(dataArea.getMinY());

                    double value = xAxis.java2DToValue(e.getX(), dataArea, xAxisEdge);
                    xLabel.setText(value);


                    org.jfree.chart.axis.ValueAxis yAxis = plot.getRangeAxis();
                    RectangleEdge yAxisEdge = plot.getRangeAxisEdge();
                    Rectangle2D subDataArea =
                    getCanvas().getRenderingInfo().getPlotInfo().getSubplotInfo(0).getDataArea();

                    yCrosshair.setStartY(y);
                    yCrosshair.setStartX(dataArea.getMinX());
                    yCrosshair.setEndX(dataArea.getMaxX());
                    yCrosshair.setEndY(y);
                    yLabel.setLayoutY(y);
                    yLabel.setLayoutX(dataArea.getMinX());
                   yLabel.setText(yAxis.java2DToValue(y, subDataArea, yAxisEdge));
                } else {
                    setCrosshairVisible(false);
                }
            });
    }

    // (other code...)

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants