Skip to content

Instantly share code, notes, and snippets.

@abhinayagarwal
Created March 10, 2014 21:28
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 abhinayagarwal/9474756 to your computer and use it in GitHub Desktop.
Save abhinayagarwal/9474756 to your computer and use it in GitHub Desktop.
BarChart with Label and refresh Data
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
import java.text.DecimalFormat;
import javafx.application.Application;
import javafx.beans.value.*;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.chart.*;
import javafx.scene.control.Button;
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 bar with a single 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 {
Button button = new Button("Refresh");
BarChart<String, Number> bc;
@Override
public void start(Stage stage) {
final CategoryAxis xAxis = new CategoryAxis();
xAxis.setLabel("Bars");
final NumberAxis yAxis = new NumberAxis();
yAxis.setLabel("Value");
bc = new BarChart<>(xAxis, yAxis);
bc.setLegendVisible(false);
XYChart.Series series1 = new XYChart.Series();
for (int i = 0; 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);
}
bc.getData().add(series1);
LevelLegend legend = new LevelLegend();
legend.setAlignment(Pos.CENTER);
VBox chartWithLegend = new VBox();
chartWithLegend.getChildren().setAll(bc, legend);
VBox.setVgrow(bc, 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 DecimalFormat df = new DecimalFormat( "$###,##0.00" );
final Text dataText = new Text(df.format(data.getYValue()) + "");
node.parentProperty().addListener(new ChangeListener<Parent>() {
@Override
public void changed(ObservableValue<? extends Parent> ov, Parent oldParent, Parent parent) {
if(null!=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
)
);
}
});
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent paramT) {
bc.getData().clear();
XYChart.Series series1 = new XYChart.Series();
for (int i = 10; i < 20; i++) {
final XYChart.Data<String, Number> data = new XYChart.Data("Value " + i, 1.0 + (Math.random()*(10-1+1)));
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);
}
bc.getData().add(series1);
}
});
}
/**
* 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"));
addRow(3, button);
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);
}
}
@abhinayagarwal
Copy link
Author

@seshukrishna
Copy link

Hi
I'm having one issue with this.
The label above the bar is sometimes getting truncated.
Is there any way to avoid the truncation of the label??

@Mattia2001TANK
Copy link

Yo i have an issue i post u the errore

Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
at DynamicallyColoredBarChartWithLabel.start(DynamicallyColoredBarChartWithLabel.java:70)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
... 1 more
Exception running application DynamicallyColoredBarChartWithLabel
C:\Users\mattia tanchis\Documents\NetBeansProjects\JavaFXApplication1\nbproject\build-impl.xml:1340: The following error occurred while executing this line:
C:\Users\mattia tanchis\Documents\NetBeansProjects\JavaFXApplication1\nbproject\build-impl.xml:981: Java returned: 1
BUILD FAILED (total time: 1 second)

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