JavaFX如何动态更改ProgressBar颜色?

时间:2012-11-20 05:44:45

标签: dynamic colors progress-bar javafx-2

我试图用this线程中的彩色进度条来解决我的问题。解决方案存在,但后来我遇到了另一个问题:我不能动态地从我的代码中更改颜色。我想从我的代码中做到这一点,而不是使用预定义的.css。一般来说,我可以做到这一点,但是当我尝试使用多个progess bar时,我遇到了一些困难。

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();
    }
}

我总是得到2个红色进度条!似乎第(1)行中的代码改变了ProgressBar类的样式,而不是实例。

另一个奇怪的时刻是删除第(1)行不会产生2个绿色进度条。所以我可以认为第(2)行是完全无用的!为什么?!这绝对是奇怪的。

有没有办法为单独的进度条设置不同的颜色?

1 个答案:

答案 0 :(得分:4)

另请参阅StackOverflow JavaFX ProgressBar Community Wiki


您可以使用一种解决方法,直到修复问题中的示例代码的错误并将其修复为止。

此答案中的代码在ProgressBar内容上执行了node lookup,然后动态地将进度条的条形颜色修改为您喜欢的任何值。

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) + "%)";
    }
  }
}

代码使用css属性的内联字符串处理来操作Region背景。未来的JavaFX版本(例如JDK8 +)将包含一个用于操作背景属性的公共Java API,从而废弃了Java程序中属性的字符串处理。

示例程序输出:

colorchooserprogress