How can I style the ProgressBar component in JavaFX
I have marked this answer as community wiki.
If you have ideas for JavaFX ProgressBar styling outside of the original initial styling queries, please edit this post to add your styling ideas (or to link to them).
set the color of the progress bar itself
Answered in:
- JavaFX ProgressBar: how to change bar color?
The answer demonstrates
- Dynamic styling of the progress bar, so that the bar's color changes depending upon the amount of progress made.
- Static styling of the progress bar, which just sets the bar's color forever to a defined color.
JavaFX 7 (caspian) on a Windows PC:
JavaFX 8 (modena) on a Mac:
Sometimes people like barbershop pole style gradients, like the bootstrap striped style:
- ProgressBar Animated Javafx
set the background color of the progress bar (not the same as setting the background color)
Define an appropriate css style for the progress bar's "track":
.progress-bar > .track {
-fx-text-box-border: forestgreen;
-fx-control-inner-background: palegreen;
}
add a custom text node on top of the progress bar (to show the different states)
Answered in:
- Draw a String onto a ProgressBar, like JProgressBar?
how to change the height of a progress bar:
Answered in:
- How to get narrow progres bar in JavaFX?
Sample CSS:
.progress-bar .bar {
-fx-padding: 1px;
-fx-background-insets: 0;
}
José Pereda gives a nice comprehensive solution for narrow progress bars in his answer to:
- How to get a small ProgressBar in JavaFX
I am looking for the css class names and the css commands
The place to look is in the default JavaFX style sheet.
- modena.css for Java 8.
- caspian.css for Java 7.
The ProgressBar style definitions for caspian (Java 7) are:
.progress-bar {
-fx-skin: "com.sun.javafx.scene.control.skin.ProgressBarSkin";
-fx-background-color:
-fx-box-border,
linear-gradient(to bottom, derive(-fx-color,30%) 5%, derive(-fx-color,-17%));
-fx-background-insets: 0, 1;
-fx-indeterminate-bar-length: 60;
-fx-indeterminate-bar-escape: true;
-fx-indeterminate-bar-flip: true;
-fx-indeterminate-bar-animation-time: 2;
}
.progress-bar .bar {
-fx-background-color:
-fx-box-border,
linear-gradient(to bottom, derive(-fx-accent,95%), derive(-fx-accent,10%)),
linear-gradient(to bottom, derive(-fx-accent,38%), -fx-accent);
-fx-background-insets: 0, 1, 2;
-fx-padding: 0.416667em; /* 5 */
}
.progress-bar:indeterminate .bar {
-fx-background-color: linear-gradient(to left, transparent, -fx-accent);
}
.progress-bar .track {
-fx-background-color:
-fx-box-border,
linear-gradient(to bottom, derive(-fx-color,-15%), derive(-fx-color,2.2%) 20%, derive(-fx-color,60%));
-fx-background-insets: 0, 1;
}
.progress-bar:disabled {
-fx-opacity: -fx-disabled-opacity;
}
The progress bar style definitions for modena (Java 8) are:
.progress-bar {
-fx-indeterminate-bar-length: 60;
-fx-indeterminate-bar-escape: true;
-fx-indeterminate-bar-flip: true;
-fx-indeterminate-bar-animation-time: 2;
}
.progress-bar > .bar {
-fx-background-color: linear-gradient(to bottom, derive(-fx-accent, -7%), derive(-fx-accent, 0%), derive(-fx-accent, -3%), derive(-fx-accent, -9%) );
-fx-background-insets: 3 3 4 3;
-fx-background-radius: 2;
-fx-padding: 0.75em;
}
.progress-bar:indeterminate > .bar {
-fx-background-color: linear-gradient(to left, transparent, -fx-accent);
}
.progress-bar > .track {
-fx-background-color:
-fx-shadow-highlight-color,
linear-gradient(to bottom, derive(-fx-text-box-border, -10%), -fx-text-box-border),
linear-gradient(to bottom,
derive(-fx-control-inner-background, -7%),
derive(-fx-control-inner-background, 0%),
derive(-fx-control-inner-background, -3%),
derive(-fx-control-inner-background, -9%)
);
-fx-background-insets: 0, 0 0 1 0, 1 1 2 1;
-fx-background-radius: 4, 3, 2; /* 10, 9, 8 */
}
The JavaFX CSS reference guide contains general information on the use of CSS in JavaFX (which differs somewhat from the use of CSS in HTML).
JavaFX ProgressBar: how to change bar color?
Answer updated to add a simple non-animated example with multiple progress bars
The code in your question should display two different colored progress bars, the fact that it doesn't is a bug in the JavaFX css processing system. Log the bug against the runtime project here: http://javafx-jira.kenai.com.
As a workaround, instead of calling setStyle on the progress bars, define the accent colors used to color progress bars within a stylesheet and add a style class to the progress bars. Then, you can create multiple progress bars within the same application, all with different colors.
As Uluk points out, you can use JavaFX 2.2 caspian.css in conjunction with the JavaFX 2 css reference guide and the JavaFX 2 css tutorial to determine how to style things.
Here is some sample code which customizes a progress bar based upon the information in those references.
Sample css:
/** progress.css
place in same directory as
ColoredProgressBarStyleSheet.java or SimpleColoredProgressBar.java
ensure build system copies the css file to the build output path */
.root { -fx-background-color: cornsilk; -fx-padding: 15; }
.progress-bar { -fx-box-border: goldenrod; }
.green-bar { -fx-accent: green; }
.yellow-bar { -fx-accent: yellow; }
.orange-bar { -fx-accent: orange; }
.red-bar { -fx-accent: red; }
Simple sample program:
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
// shows multiple progress bars drawn in different colors.
public class SimpleColoredProgressBar extends Application {
public static void main(String[] args) { launch(args); }
@Override public void start(Stage stage) {
final VBox layout = new VBox(10);
layout.setAlignment(Pos.CENTER);
layout.getChildren().setAll(
new ColoredProgressBar("red-bar", 0.2),
new ColoredProgressBar("orange-bar", 0.4),
new ColoredProgressBar("yellow-bar", 0.6),
new ColoredProgressBar("green-bar", 0.8)
);
layout.getStylesheets().add(getClass().getResource("progress.css").toExternalForm());
stage.setScene(new Scene(layout));
stage.show();
}
class ColoredProgressBar extends ProgressBar {
ColoredProgressBar(String styleClass, double progress) {
super(progress);
getStyleClass().add(styleClass);
}
}
}
Simple sample program output:
More complicated sample program with a single animated progress bar which changes color dynamically depending on the amount of progress made:
import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.value.*;
import javafx.event.*;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
// shows a progress bar whose bar changes color depending on the amount of progress.
public class ColoredProgressBarStyleSheet extends Application {
public static void main(String[] args) { launch(args); }
private static final String RED_BAR = "red-bar";
private static final String YELLOW_BAR = "yellow-bar";
private static final String ORANGE_BAR = "orange-bar";
private static final String GREEN_BAR = "green-bar";
private static final String[] barColorStyleClasses = { RED_BAR, ORANGE_BAR, YELLOW_BAR, GREEN_BAR };
@Override public void start(Stage stage) {
final ProgressBar bar = new ProgressBar();
final Timeline timeline = new Timeline(
new KeyFrame(Duration.millis(0), new KeyValue(bar.progressProperty(), 0)),
new KeyFrame(Duration.millis(3000), new KeyValue(bar.progressProperty(), 1))
);
Button reset = new Button("Reset");
reset.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent event) {
timeline.playFromStart();
}
});
bar.progressProperty().addListener(new ChangeListener<Number>() {
@Override public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
double progress = newValue == null ? 0 : newValue.doubleValue();
if (progress < 0.2) {
setBarStyleClass(bar, RED_BAR);
} else if (progress < 0.4) {
setBarStyleClass(bar, ORANGE_BAR);
} else if (progress < 0.6) {
setBarStyleClass(bar, YELLOW_BAR);
} else {
setBarStyleClass(bar, GREEN_BAR);
}
}
private void setBarStyleClass(ProgressBar bar, String barStyleClass) {
bar.getStyleClass().removeAll(barColorStyleClasses);
bar.getStyleClass().add(barStyleClass);
}
});
final VBox layout = new VBox(10);
layout.setAlignment(Pos.CENTER);
layout.getChildren().setAll(bar, reset);
layout.getStylesheets().add(getClass().getResource("progress.css").toExternalForm());
stage.setScene(new Scene(layout));
stage.show();
timeline.play();
}
}
More complicated sample program output:
Change style of progressbar javaFX
Just use an external CSS file and set a background image on the bar. The bar itself is represented by a Region
with style class bar
(see docs), so you just need something like
.progress-bar > .bar {
-fx-background-image: url("http://upload.wikimedia.org/wikipedia/commons/c/ce/Train_icon_small.png");
-fx-background-position: right ;
-fx-background-color: transparent ;
-fx-background-repeat: repeat-x ;
}
Complete example:
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TrainProgressBar extends Application {
@Override
public void start(Stage primaryStage) {
ProgressBar progressBar = new ProgressBar();
progressBar.setProgress(0);
Button startButton = new Button("Start");
startButton.setOnAction(e -> {
startButton.setDisable(true);
Task<Void> task = new Task<Void>() {
@Override
public Void call() throws Exception {
for (int i = 0; i < 100; i++) {
Thread.sleep(20);
updateProgress(i, 100);
}
updateProgress(100, 100);
return null ;
}
};
progressBar.progressProperty().bind(task.progressProperty());
task.setOnSucceeded(evt -> startButton.setDisable(false));
new Thread(task){{setDaemon(true);}}.start();
});
VBox root = new VBox(15, progressBar, startButton);
Scene scene = new Scene(root, 250, 100);
scene.getStylesheets().add("train-progress-bar.css");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
with train-progress-bar.css:
.root {
-fx-padding: 10 ;
-fx-alignment: center ;
}
.progress-bar > .bar {
-fx-background-image: url(http://upload.wikimedia.org/wikipedia/commons/c/ce/Train_icon_small.png);
-fx-background-position: right ;
-fx-background-color: transparent ;
-fx-background-repeat: repeat-x ;
}
Change JavaFX progress bar style
Simply overwrite the color constant -fx-accent
the gradient colors are derived from:
.progress-bar > .bar {
-fx-accent: green;
-fx-background-color: linear-gradient(
from 0px .75em to .75em 0px,
repeat,
-fx-accent 0%,
-fx-accent 49%,
derive(-fx-accent, 30%) 50%,
derive(-fx-accent, 30%) 99%
);
}
JavaFX How to change ProgressBar color dynamically?
See also the StackOverflow JavaFX ProgressBar Community Wiki.
There is a workaround you can use until a bug to fix the sample code in your question is filed and fixed.
The code in this answer does a node lookup on the ProgressBar
contents, then dynamically modifies the bar colour of the progress bar to any value you like.
import javafx.application.Application;
import javafx.beans.value.*;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class ProgressBarDynamicColor extends Application {
public static void main(String[] args) { launch(args); }
@Override public void start(Stage stage) {
PickedColorBar aquaBar = new PickedColorBar(0.4, Color.AQUA);
PickedColorBar fireBar = new PickedColorBar(0.6, Color.FIREBRICK);
HBox layout = new HBox(20);
layout.getChildren().setAll(aquaBar, fireBar);
layout.setStyle("-fx-background-color: -fx-box-border, cornsilk; -fx-padding: 15;");
stage.setScene(new Scene(layout));
stage.show();
aquaBar.wasShown();
fireBar.wasShown();
}
class PickedColorBar extends VBox {
private final ProgressBar bar;
private final ColorPicker picker;
private boolean wasShownCalled = false;
final ChangeListener<Color> COLOR_LISTENER = new ChangeListener<Color>() {
@Override public void changed(ObservableValue<? extends Color> value, Color oldColor, Color newColor) {
setBarColor(bar, newColor);
}
};
public PickedColorBar(double progress, Color initColor) {
bar = new ProgressBar(progress);
picker = new ColorPicker(initColor);
setSpacing(10);
setAlignment(Pos.CENTER);
getChildren().setAll(bar, picker);
}
// invoke only after the progress bar has been shown on a stage.
public void wasShown() {
if (!wasShownCalled) {
wasShownCalled = true;
setBarColor(bar, picker.getValue());
picker.valueProperty().addListener(COLOR_LISTENER);
}
}
private void setBarColor(ProgressBar bar, Color newColor) {
bar.lookup(".bar").setStyle("-fx-background-color: -fx-box-border, " + createGradientAttributeValue(newColor));
}
private String createGradientAttributeValue(Color newColor) {
String hsbAttribute = createHsbAttributeValue(newColor);
return "linear-gradient(to bottom, derive(" + hsbAttribute+ ",30%) 5%, derive(" + hsbAttribute + ",-17%))";
}
private String createHsbAttributeValue(Color newColor) {
return
"hsb(" +
(int) newColor.getHue() + "," +
(int) (newColor.getSaturation() * 100) + "%," +
(int) (newColor.getBrightness() * 100) + "%)";
}
}
}
The code uses inlined string processing of css attributes to manipulate Region backgrounds. Future JavaFX versions (e.g. JDK8+) will include a public Java API to manipulate background attributes, making obsolete the string processing of attributes from the Java program.
Sample program output:
How do you make a gradient progress bar in JavaFX?
You just have to use CSS to select the bar
of the progress-bar
:
.progress-bar .bar {
-fx-background-color: linear-gradient(to right, #87CEEB, #2980b9);
}
Then just add your stylesheet to your scene:
scene.getStylesheets().add("Style.css");
How to get narrow progres bar in JavaFX?
You'll have to mess around with the styling to get it any smaller. I really recommend taking a look a the caspian.css
that's included with Javafx - that's the default style sheet. It helps a lot when trying to override the look and feel of the default skins. Here's an example I put together that shows how it can be done:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ProgressBarTest extends Application {
public static void main(String[] args) { launch(args); }
@Override
public void start(final Stage stage) throws Exception {
//All the controls are added here
VBox box = new VBox();
box.getStylesheets().add("test.css");
ProgressBar pb = new ProgressBar(50);
box.getChildren().add(pb);
//Setting up your scene
Scene scene = new Scene(box);
stage.setScene(scene);
stage.show();
}
}
And here's the test.css I loaded up:
.progress-bar .bar {-fx-padding:1px; -fx-background-insets:0;}
And here is the output of the test app:
How to set specific css value for javaFX ProgressBar during Runtime?
I don't think this is possible using CSS alone. However a customized Skin
could be used that replaces the bar
Node
with a ImageView
and uses the bar
as clip instead:
progress.BarBackgroundProgressBarSkin
public class BarBackgroundProgressBarSkin extends ProgressBarSkin {
public BarBackgroundProgressBarSkin(ProgressBar control) {
super(control);
}
private ImageView barBackground;
@Override
protected void initialize() {
super.initialize();
barBackground = new ImageView();
barBackground.setManaged(false);
barBackground.setPreserveRatio(false);
barBackground.getStyleClass().setAll("bar-background");
int barIndex;
List<Node> children = getChildren();
int size = children.size();
for (barIndex = 0; barIndex < size && !children.get(barIndex).getStyleClass().contains("bar"); barIndex++) {
}
Region bar = (Region) children.set(barIndex, barBackground);
barBackground.setClip(bar);
// fill the bar for clipping
bar.setBackground(new Background(new BackgroundFill(Color.WHITE, new CornerRadii(2), new Insets(3, 3, 4, 3))));
}
@Override
protected void layoutChildren(double x, double y, double w, double h) {
// set pos
barBackground.setLayoutX(x);
barBackground.setLayoutY(y);
// set size
barBackground.setFitHeight(h);
barBackground.setFitWidth(w);
super.layoutChildren(x, y, w, h);
}
}
style.css
.progress-bar {
-fx-skin: 'progress.BarBackgroundProgressBarSkin';
}
.progress-bar > .bar-background {
/* your image goes here */
-fx-image: url('http://i.stack.imgur.com/glUAd.png');
}
.progress-bar > .track {
-fx-background-color: transparent;
}
Demo
@Override
public void start(Stage primaryStage) {
ProgressBar progressBar = new ProgressBar();
StackPane root = new StackPane();
root.getChildren().add(progressBar);
progressBar.setPrefSize(300, 18);
Scene scene = new Scene(root, 200, 200);
scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
Timeline tl = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(progressBar.progressProperty(), 0d)),
new KeyFrame(Duration.seconds(10), new KeyValue(progressBar.progressProperty(), 1d, Interpolator.EASE_OUT))
);
tl.setCycleCount(Animation.INDEFINITE);
tl.play();
primaryStage.setScene(scene);
primaryStage.show();
}
Related Topics
Remove HTML Tags from a String
How to Allow All Network Connection Types Http and Https in Android (9) Pie
One Time Login in App - Firebaseauth
Java Using Much More Memory Than Heap Size (Or Size Correctly Docker Memory Limit)
What Does a "Cannot Find Symbol" or "Cannot Resolve Symbol" Error Mean
How to Convert My Java Program to an .Exe File
How to Fix a Nosuchmethoderror
Change Private Static Final Field Using Java Reflection
Generating Unique Random Numbers in Java
How to Send Http Request in Java
Why Doesn't Recyclerview Have Onitemclicklistener()
Showing Firebase Data in Listview
Error: Could Not Find or Load Main Class
Com.MySQL.Jdbc.Exceptions.Jdbc4.Communicationsexception: Communications Link Failure