Search code examples
javajavafxchartsanalyticsgraphing

Double sided bar chart in JavaFX


For a project I am working on, I would like to display data as a continually updating double sided bar chart (or double sided histogram) in JavaFX. I have successfully created a horizontal bar chart where the bars extend from only one side of axis, but not from both sides.

An example of what I want to do would be, on a chart, each row (or bar) represents a store, the left side represents what percentage is currently female and the right the percentage currently male. As customers enter and leave the store, this chart updates to show current gender percentage, with it always adding up to 100% unless there are no customers. In which case there is no bar. This means that, unless there are no customers, the bar will always be the same length, just shifted to each side. The whole chart shows maybe 5 different stores, so has five different bars with gender representations.

I don't have enough reputation to post an image so here is a link to what I want it to look like.

This is a link that looks like what I can currently make.

Thank you!


Solution

  • Originally I tried to use a BarChart object to graph a double sided bar chart, but after looking at this question I realized that a StackedBarChart had what I was looking for. This is the code I used to create a double sided histogram/bar chart for anyone else wondering how to do this:

        import java.util.Arrays;
        import javafx.application.Application;
        import javafx.collections.FXCollections;
        import javafx.scene.Scene;
        import javafx.scene.chart.CategoryAxis;
        import javafx.scene.chart.NumberAxis;
        import javafx.scene.chart.StackedBarChart;
        import javafx.scene.chart.XYChart;
        import javafx.stage.Stage;
    
        public class HorizontalHistogramTest extends Application{
    
    
            final static String austria = "Austria";
            final static String brazil = "Brazil";
            final static String france = "France";
            final static String italy = "Italy";
            final static String usa = "USA";
            final CategoryAxis xAxis = new CategoryAxis();
            final NumberAxis yAxis = new NumberAxis();
            final StackedBarChart<Number, String> sbc =
            new StackedBarChart<Number,String>(yAxis, xAxis);
            final XYChart.Series<Number,String> series1 =
            new XYChart.Series<Number,String>();
    
    @Override
    public void start(Stage stage) {
        stage.setTitle("Bar Chart Sample");
        sbc.setTitle("Country Summary");
        xAxis.setLabel("Country");
        xAxis.setCategories(FXCollections.<String>observableArrayList(
                Arrays.asList(austria, brazil, france, italy, usa)));
        yAxis.setLabel("Percent");
        // plus value
        series1.getData().add(new XYChart.Data<Number,String>(10, austria));
        series1.getData().add(new XYChart.Data<Number,String>(50, brazil));
        series1.getData().add(new XYChart.Data<Number,String>(40, france));
        series1.getData().add(new XYChart.Data<Number,String>(50, italy));
        series1.getData().add(new XYChart.Data<Number,String>(60, usa));
        // minus value
        series1.getData().add(new XYChart.Data<Number,String>(-90, austria));
        series1.getData().add(new XYChart.Data<Number,String>(-50, brazil));
        series1.getData().add(new XYChart.Data<Number,String>(-60, france));
        series1.getData().add(new XYChart.Data<Number,String>(-50, italy));
        series1.getData().add(new XYChart.Data<Number,String>(-40, usa));
    
        Scene scene = new Scene(sbc, 800, 600);
        sbc.getData().addAll(series1);
        stage.setScene(scene);
        stage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
    }