Forum Stats

  • 3,836,810 Users
  • 2,262,195 Discussions
  • 7,900,117 Comments

Discussions

how to add 3 legends for a single series barchart?? JAVAFX

HassanShakeel
HassanShakeel Member Posts: 4
edited Mar 12, 2013 9:03PM in JavaFX 2.0 and Later
Here is my code to generate 10 bars of different colors. I want to add legend respectively but it only one shows yellow legend

1. I think it shows only 1 color because there is only 1 series. Is it possible to add more than 1 legend for a single series?

or

2. or can i display another image for legend in barchart??

output :http://i.stack.imgur.com/fSNu7.png

file i want to display in barchart:http://i.stack.imgur.com/cchch.png
..
public class DynamicallyColoredBarChart extends Application {

    @Override
    public void start(Stage stage) {
        final CategoryAxis xAxis = new CategoryAxis();
        xAxis.setLabel("Bars");
        final NumberAxis yAxis = new NumberAxis();
        yAxis.setLabel("Value");

        final BarChart<String, Number> bc = new BarChart<>(xAxis, yAxis);
        bc.setLegendVisible(false);

        XYChart.Series series1 = new XYChart.Series();

        for (int i = 0; i < 10; i++) {
            // change color of bar if value of i is >5 than red if i>8 than blue
            final XYChart.Data<String, Number> data = new XYChart.Data("Value " + i, i);
            data.nodeProperty().addListener(new ChangeListener<Node>() {
                @Override
                public void changed(ObservableValue<? extends Node> ov, Node oldNode, Node newNode) {
                    if (newNode != null) {
                        if (data.getYValue().intValue() > 8) {
                            newNode.setStyle("-fx-bar-fill: navy;");
                        } else if (data.getYValue().intValue() > 5) {
                            newNode.setStyle("-fx-bar-fill: red;");
                        }
                    }
                }
            });
            series1.getData().add(data);
        }
        bc.getData().add(series1);
        stage.setScene(new Scene(bc));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
...
Edited by: 993431 on Mar 12, 2013 1:42 PM
Tagged:

Answers

  • jsmith
    jsmith Member Posts: 2,856
    Either:
    1. Use a chart which displays multiple series, then you can allow the built-in legend to show OR
    2. Use a single dynamically colored series have you have done and create your own custom legend.
    import javafx.application.Application;
    import javafx.scene.*;
    import javafx.scene.chart.*;
    import javafx.stage.Stage;
    
    public class ThreeSeriesBarChart extends Application {
      @Override public void start(Stage stage) {
        final CategoryAxis xAxis = new CategoryAxis();
        xAxis.setLabel("Bars");
        final NumberAxis yAxis = new NumberAxis();
        yAxis.setLabel("Value");
    
        final BarChart<String, Number> bc = new BarChart<>(xAxis, yAxis);
        XYChart.Series lowSeries = new XYChart.Series();
        lowSeries.setName("Not Achieved");
        XYChart.Series medSeries = new XYChart.Series();
        medSeries.setName("Achieved");
        XYChart.Series hiSeries  = new XYChart.Series();
        hiSeries.setName("Exceeded");
        bc.setBarGap(0);
        bc.setCategoryGap(0);
    
        for (int i = 0; i < 10; i++) {
          final XYChart.Data<String, Number> data = new XYChart.Data("Value " + i, i);
          if (data.getYValue().intValue() > 8) {
            hiSeries.getData().add(data);
          } else if (data.getYValue().intValue() > 5) {
            medSeries.getData().add(data);
          } else {
            lowSeries.getData().add(data);
          }
        }
        bc.getData().setAll(lowSeries, medSeries, hiSeries);
        
        bc.getStylesheets().add(getClass().getResource("colored-chart.css").toExternalForm());
        
        stage.setScene(new Scene(bc));
        stage.show();
      }
    
      public static void main(String[] args) {
        launch(args);
      }
    }
    import javafx.application.Application;
    import javafx.beans.value.*;
    import javafx.geometry.Pos;
    import javafx.scene.*;
    import javafx.scene.chart.*;
    import javafx.scene.control.Label;
    import javafx.scene.layout.*;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.*;
    import javafx.stage.Stage;
    
    public class DynamicallyColoredBarChart extends Application {
      @Override public void start(Stage stage) {
        final CategoryAxis xAxis = new CategoryAxis();
        xAxis.setLabel("Bars");
        final NumberAxis yAxis = new NumberAxis();
        yAxis.setLabel("Value");
    
        final BarChart<String, Number> bc = new BarChart<>(xAxis, yAxis);
        bc.setLegendVisible(false);
    
        XYChart.Series series1 = new XYChart.Series();
    
        for (int i = 0; i < 10; i++) {
          // change color of bar if value of i is >5 than red if i>8 than blue
          final XYChart.Data<String, Number> data = new XYChart.Data("Value " + i, i);
          data.nodeProperty().addListener(new ChangeListener<Node>() {
            @Override
            public void changed(ObservableValue<? extends Node> ov, Node oldNode, Node newNode) {
              if (newNode != null) {
                if (data.getYValue().intValue() > 8) {
                  newNode.setStyle("-fx-bar-fill: -fx-exceeded;");
                } else if (data.getYValue().intValue() > 5) {
                  newNode.setStyle("-fx-bar-fill: -fx-achieved;");
                } else {
                  newNode.setStyle("-fx-bar-fill: -fx-not-achieved;");
                }
              } 
            }
          });
          series1.getData().add(data);
        }
        bc.getData().add(series1);
    
        LevelLegend legend = new LevelLegend();
        legend.setAlignment(Pos.CENTER);
    
        VBox chartWithLegend = new VBox();
        chartWithLegend.getChildren().setAll(bc, legend);
        
        chartWithLegend.getStylesheets().add(getClass().getResource("colored-chart.css").toExternalForm());
        
        stage.setScene(new Scene(chartWithLegend));
        stage.show();
      }
      
      class LevelLegend extends GridPane {
        LevelLegend() {
          setHgap(10);
          setVgap(10);
          addRow(0, createSymbol("-fx-exceeded"),     new Label("Exceeded"));
          addRow(1, createSymbol("-fx-achieved"),     new Label("Achieved"));
          addRow(2, createSymbol("-fx-not-achieved"), new Label("Not Achieved"));
          
          getStyleClass().add("level-legend");
        }
        
        private Node createSymbol(String fillStyle) {
          Shape symbol = new Ellipse(10, 5, 10, 5);
          symbol.setStyle("-fx-fill: " + fillStyle);
          symbol.setStroke(Color.BLACK);
          symbol.setStrokeWidth(2);
          
          return symbol;
        }
      }
    
      public static void main(String[] args) { launch(args); }
    }
    /** colored-chart.css: place in same directory as other bar chart application files and setup your build system to copy it to the output directory */
    .root {
      -fx-not-achieved: red;
      -fx-achieved:     green;
      -fx-exceeded:     blue;
    }
    
    .default-color0.chart-bar { -fx-bar-fill: -fx-not-achieved; }
    .default-color1.chart-bar { -fx-bar-fill: -fx-achieved; }
    .default-color2.chart-bar { -fx-bar-fill: -fx-exceeded; }
    
    .level-legend {
      -fx-padding: 10; 
      -fx-border-width: 2; 
      -fx-background-color: rgba(211, 211, 211, 0.5); 
      -fx-border-color: derive(rgba(211, 211, 211, 0.7), 10%);
    }
  • Thank you so much your code works .. 1 more question is it possible to add value label of each bar on top of each bar??
    and again thanks :)
  • jsmith
    jsmith Member Posts: 2,856
    is it possible to add value label of each bar on top of each bar
    Yes, see: "how to display bar value on top of bar javafx"
    http://stackoverflow.com/questions/15237192/how-to-display-bar-value-on-top-of-bar-javafx/15375168
This discussion has been closed.