Reputation: 65
Good day,
My Issue
I'm programming a JavaFX application that makes use of LineCharts. I would like to add the ability to create discontinuities on the LineChart. I would like to do this so that when my program reads data from a database, it will break the line where portions of data are missing. In my programs current form, the graph looks like this. I have obtained the following code below from this post on SO and I've been attempting to adapt it to suit the needs of my program.
package application;
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.Axis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.shape.Circle;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
NumberAxis xAxis = new NumberAxis();
NumberAxis yAxis = new NumberAxis();
MyLineChart chart = new MyLineChart(xAxis, yAxis, Arrays.asList(5));
XYChart.Series<Number, Number> serie = new Series<>();
serie.getData().add(new Data<Number, Number>(0, 5));
serie.getData().add(new Data<Number, Number>(1, 5));
serie.getData().add(new Data<Number, Number>(2, 5));
serie.getData().add(new Data<Number, Number>(3, 5));
serie.getData().add(new Data<Number, Number>(4, 5));
serie.getData().add(new Data<Number, Number>(5, -5));
serie.getData().add(new Data<Number, Number>(6, -5));
serie.getData().add(new Data<Number, Number>(7, -5));
chart.getData().add(serie);
Path p = (Path) serie.getNode();
Scene scene = new Scene(chart,400,400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private static class MyLineChart extends LineChart<Number,Number>{
private List<Integer> breakpointIndex;
public MyLineChart(Axis<Number> xAxis, Axis<Number> yAxis, List<Integer> breakpointIndex) {
super(xAxis, yAxis);
this.breakpointIndex = breakpointIndex;
}
@Override
protected void layoutPlotChildren() {
super.layoutPlotChildren();
Path p = (Path) getData().get(0).getNode();
breakpointIndex.forEach(i ->{
Data<Number, Number> discontinuousPoint = getData().get(0).getData().get(i+1);
p.getElements().add(i+1, new MoveTo(getXAxis().getDisplayPosition( discontinuousPoint.getXValue()), getYAxis().getDisplayPosition(discontinuousPoint.getYValue())));
});
System.out.println("\nnew Path :");
p.getElements().forEach(e -> System.out.println("p : " + e));
}
}
}
This code works perfectly in the above form, but it does not display multiple discontinuities properly. I have taken a screenshot of the output when I add the following code to the above program:
MyLineChart chart = new MyLineChart(xAxis, yAxis, Arrays.asList(5, 7)); //added 7 to the array
.....
serie.getData().add(new Data<Number, Number>(8, 7));
What I have done
I have tried removing the element where the discontinuity occurs but this results in parts of the graph not having a line through the points. This result can be seen here.
I've also added the above code (with a few modifications to the data types) to my application and I get this result.
Upvotes: 3
Views: 445
Reputation: 632
Perhaps you could model a discontinuous line as two or more line sections? The graphing routines are unaware of the discontinuity, and will assume all data points that you supply as one set are connected.
I would think about creating a higher level object that contains zero or more data series each represented as a separate 'line' on the graph. The higher level object would be responsible for setting the appearance of its contained line so all the segments would appear the same (colour, line style, data point symbol). The user will interpret this as a single line with discontinuities.
Upvotes: 1