I have usual CSS for my ProgressBar
:
.progress-bar > .track {
-fx-background-color: transparent;
}
.progress-bar > .bar {
-fx-background-color: transparent;
-fx-background-image: url('/images/progress_bar.png');
-fx-background-size: 1600px 50px;
-fx-background-repeat: no-repeat;
}
Image progress_bar.png
is 3-colored bar that changes from green to red as it reaches it's end. It works nicely when application is run.
My problem are those hard coded values for background size. This work on full HD displays perfectly but on 1366x768 most of yellow/red parts are cut out. I would like to set this property during run-time to match screen size. Is this possible?
I tried to use setStyle()
method in ProgressBar
but without success. Maybe I am just doing it wrong so if anyone has working example...
I also tried to set width to 100% (instead of px) but that does not work either. It just shows compressed bar and then it stretches it to 100% width.
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);
}
}
.progress-bar {
-fx-skin: 'progress.BarBackgroundProgressBarSkin';
}
.progress-bar > .bar-background {
/* your image goes here */
-fx-image: url('https://i.sstatic.net/glUAd.png');
}
.progress-bar > .track {
-fx-background-color: transparent;
}
@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();
}