Skip to content

Instantly share code, notes, and snippets.

@KhaledLela
Last active December 20, 2015 04:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KhaledLela/6071422 to your computer and use it in GitHub Desktop.
Save KhaledLela/6071422 to your computer and use it in GitHub Desktop.
JavaFx adding a text label on top of StackedBarChart
import javafx.application.Application;
import javafx.beans.value.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Bounds;
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.scene.text.Text;
import javafx.stage.Stage;
/**
* Displays a Stackedbar with a multi series whose bars are different colors depending
* upon the bar value. A custom legend is created and displayed for the bar
* data. Bars in the chart are customized to include a text label of the bar's
* data value above the bar.
*/
public class DynamicallyColoredBarChartWithLabel extends Application {
@Override
public void start(Stage stage) {
final NumberAxis yAxis = new NumberAxis();
yAxis.setLabel("Value");
String[] years = {"2007", "2008", "2009"};
final CategoryAxis xAxis = new CategoryAxis(FXCollections.<String>observableArrayList(years));
xAxis.setLabel("Bars");
// final StackedBarChart<String, Number> bc = new StackedBarChart<>(xAxis, yAxis);
// bc.setLegendVisible(false);
//
// XYChart.Series<String,Number> series1 = new XYChart.Series();
// XYChart.Series<String,Number> series2 = new XYChart.Series();
// for (int i = 1; i <= 10; i++) {
// 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, final Node node) {
//// if (node != null) {
//// setNodeStyle(data);
//// displayLabelForData(data);
//// }
//// }
//// });
// series1.getData().add(data);
// }
ObservableList<StackedBarChart.Series> barChartData = FXCollections.observableArrayList(
new StackedBarChart.Series("Region 1", FXCollections.observableArrayList(
new StackedBarChart.Data(years[0], 567d),
new StackedBarChart.Data(years[1], 1292d),
new StackedBarChart.Data(years[2], 1292d))),
new StackedBarChart.Series("Region 2", FXCollections.observableArrayList(
new StackedBarChart.Data(years[0], 956),
new StackedBarChart.Data(years[1], 1665),
new StackedBarChart.Data(years[2], 2559))),
new StackedBarChart.Series("Region 3", FXCollections.observableArrayList(
new StackedBarChart.Data(years[0], 1154),
new StackedBarChart.Data(years[1], 1927),
new StackedBarChart.Data(years[2], 2774))));
final XYChart.Series<String, Number> lastSeries = barChartData.get(barChartData.size() - 1);
for (final XYChart.Data<String, Number> data : lastSeries.getData()) {
data.nodeProperty().addListener(new ChangeListener<Node>() {
@Override
public void changed(ObservableValue<? extends Node> ov, Node oldNode, final Node node) {
if (node != null) {
// setNodeStyle(data);
displayLabelForData(data);
}
}
});
}
StackedBarChart<String, Number> chart = new StackedBarChart(xAxis, yAxis, barChartData, 25.0d);
LevelLegend legend = new LevelLegend();
legend.setAlignment(Pos.CENTER);
VBox chartWithLegend = new VBox();
chartWithLegend.getChildren().setAll(chart, legend);
VBox.setVgrow(chart, Priority.ALWAYS);
chartWithLegend.getStylesheets().add(getClass().getResource("colored-chart.css").toExternalForm());
stage.setScene(new Scene(chartWithLegend));
stage.setMinHeight(400);
stage.setMinWidth(400);
stage.show();
}
/**
* Change color of bar if value of i is <5 then red, if >5 then green if i>8
* then blue
*/
private void setNodeStyle(XYChart.Data<String, Number> data) {
Node node = data.getNode();
if (data.getYValue().intValue() > 8) {
node.setStyle("-fx-bar-fill: -fx-exceeded;");
} else if (data.getYValue().intValue() > 5) {
node.setStyle("-fx-bar-fill: -fx-achieved;");
} else {
node.setStyle("-fx-bar-fill: -fx-not-achieved;");
}
}
/**
* places a text label with a bar's value above a bar node for a given
* XYChart.Data
*/
private void displayLabelForData(XYChart.Data<String, Number> data) {
final Node node = data.getNode();
final Text dataText = new Text(data.getYValue() + "");
node.parentProperty().addListener(new ChangeListener<Parent>() {
@Override
public void changed(ObservableValue<? extends Parent> ov, Parent oldParent, Parent parent) {
Group parentGroup = (Group) parent;
parentGroup.getChildren().add(dataText);
}
});
node.boundsInParentProperty().addListener(new ChangeListener<Bounds>() {
@Override
public void changed(ObservableValue<? extends Bounds> ov, Bounds oldBounds, Bounds bounds) {
dataText.setLayoutX(
Math.round(
bounds.getMinX() + bounds.getWidth() / 2 - dataText.prefWidth(-1) / 2));
dataText.setLayoutY(
Math.round(
bounds.getMinY() - dataText.prefHeight(-1) * 0.5));
}
});
}
/**
* A simple custom legend for a three valued chart.
*/
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");
}
/**
* Create a custom symbol for a custom chart legend with the given
* fillStyle style string.
*/
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);
}
}
@jeremyhalin
Copy link

But did you try updating data ? Labels on top of bar chart stay after updating data for me... It's annoying and I don't know how to remove them.
http://stackoverflow.com/questions/34286062/how-to-clear-text-added-in-a-javafx-barchart

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment