Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX ProgressBar: how to change bar color?

I'm trying to change the color of bar in ProgressBar with

pBar.setStyle("-fx-accent: green");

but I have encountered a problem: that doesn't seem to work right for me! (Or I just don't understand something)

here is the code:

public class JavaFXApplication36 extends Application {

@Override
public void start(Stage primaryStage) {
AnchorPane root = new AnchorPane();
ProgressBar pbRed = new ProgressBar(0.4);
ProgressBar pbGreen = new ProgressBar(0.6);
pbRed.setLayoutY(10);
pbGreen.setLayoutY(30);

pbRed.setStyle("-fx-accent: red;");       // line (1)
pbGreen.setStyle("-fx-accent: green;");   // line (2)

root.getChildren().addAll(pbRed, pbGreen);
Scene scene = new Scene(root, 150, 50);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
}

I always get 2 red progressbars with it! It seems that code in line (1) changes the style of ProgressBar class, not the instance.

Another strange moment is that deleting line (1) don't result in 2 green progress bars. So I can figure that line (2) is completely useless!! WHY?! That's definitely getting odd.

Is there any way to set separate colors for separate progressbars?

like image 484
Chechulin Avatar asked Nov 13 '12 07:11

Chechulin


People also ask

How do I add a progress bar in JavaFX?

Creating Progress ControlsProgressBar pb = new ProgressBar(0.6); ProgressIndicator pi = new ProgressIndicator(0.6); You can also create the progress controls without parameters by using an empty constructor. In that case, you can assign the value by using the setProgress method.

Does JavaFX provide a progress monitor control?

ProgressIndicator is a part of JavaFX package. It's a circular control which is used for indicating progress, either infinite or finite.


2 Answers

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:

coloredbars

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:

sample program output

like image 183
jewelsea Avatar answered Oct 11 '22 18:10

jewelsea


You should to override (or customize) the style with JavaFX CSS selectors. See caspian.css for more information. In your own stylesheet define:

.progress-bar .bar {
    -fx-background-color:
        -fx-box-border,
        linear-gradient(to bottom, derive(-fx-accent,95%), derive(-fx-accent,10%)),
        red; /* this line is the background color of the bar */
    -fx-background-insets: 0, 1, 2;
    -fx-padding: 0.416667em; /* 5 */
}
like image 31
Uluk Biy Avatar answered Oct 11 '22 19:10

Uluk Biy