如何在 javaFX 中将颜色从 ColorPicker 转换为 String 值

Posted

技术标签:

【中文标题】如何在 javaFX 中将颜色从 ColorPicker 转换为 String 值【英文标题】:How to convert color from ColorPicker to String value in javaFX 【发布时间】:2020-06-11 22:24:02 【问题描述】:

我想让用户使用 ColorPicker 选择颜色,然后使用该颜色来更改按钮的颜色。 JavaFX

    ColorPicker cp = new ColorPicker();
            cp.setOnAction(e -> 
                Color c = cp.getValue();
                System.out.println(c);
            );

在 println 中,它会给出类似 0xe6e64dff,0xccffccff...的答案。

如果我想把按钮染成蓝色,我需要使用这个:

    Button button = new Button();
    button.setStyle("-fx-background-color: #ff0000; ");

所以我假设我必须先将颜色值转换为字符串才能使用它?或者我该怎么做? 如何让选择的颜色在 setStyle 行中可用?

【问题讨论】:

这能回答你的问题吗? How to get hex web String from JavaFX ColorPicker color? 【参考方案1】:

Color 转换为十六进制字符串

您可以使用以下命令从Color 创建一个十六进制字符串:

private static String toHexString(Color color) 
  int r = ((int) Math.round(color.getRed()     * 255)) << 24;
  int g = ((int) Math.round(color.getGreen()   * 255)) << 16;
  int b = ((int) Math.round(color.getBlue()    * 255)) << 8;
  int a = ((int) Math.round(color.getOpacity() * 255));
  return String.format("#%08X", (r + g + b + a));

这还将包括颜色的 alpha(即不透明度)。请注意,JavaFX CSS Reference Guide 没有记录对 4 位/8 位十六进制值的任何支持:

RGB Hex: RGB 值的十六进制格式是一个“#”,紧跟三个或六个十六进制字符。三位 RGB 符号 (#rgb) 通过复制数字而不是添加零转换为六位形式 (#rrggbb)。例如,#fb0 扩展为 #ffbb00。这确保了白色 (#ffffff) 可以用简写符号 (#fff) 指定,并消除对显示颜色深度的任何依赖。

但是,Color#web(String) 的文档说支持以下格式:

带有可选的十六进制 alpha 通道html 长格式或短格式十六进制字符串 [强调]。十六进制值前面可以是 "0x""#",并且可以是 000xFF 范围内的 2 位数字或 0F 范围内的单个数字。

另请注意,它表示十六进制值可能以 either 0x# 为前缀。

以下是使用上述实用方法的示例:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ColorPicker;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class App extends Application 

  @Override
  public void start(Stage primaryStage) 
    StackPane root = new StackPane();

    ColorPicker picker = new ColorPicker();
    root.getChildren().add(picker);
    picker.setOnAction(
        event -> 
          event.consume();

          Color value = picker.getValue();
          if (value == null) 
            root.setStyle(null);
           else 
            String style = String.format("-fx-background-color: %s;", toHexString(value));
            root.setStyle(style);
          
        );

    primaryStage.setScene(new Scene(root, 500, 300));
    primaryStage.setTitle("Color to Hexadecimal Example");
    primaryStage.show();
  

  private static String toHexString(Color color) 
    int r = ((int) Math.round(color.getRed()     * 255)) << 24;
    int g = ((int) Math.round(color.getGreen()   * 255)) << 16;
    int b = ((int) Math.round(color.getBlue()    * 255)) << 8;
    int a = ((int) Math.round(color.getOpacity() * 255));

    return String.format("#%08X", (r + g + b + a));
  


背景属性

还有另一种方法可以完成您正在做的事情。您可以直接设置Region#background 属性,而不是设置style,这需要将Color 转换为String。这是一个例子:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ColorPicker;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class App extends Application 

  @Override
  public void start(Stage primaryStage) 
    StackPane root = new StackPane();

    ColorPicker picker = new ColorPicker();
    root.getChildren().add(picker);
    picker.setOnAction(
        event -> 
          event.consume();

          Color value = picker.getValue();
          if (value == null) 
            root.setBackground(null);
           else 
            root.setBackground(new Background(new BackgroundFill(value, null, null)));
          
        );

    primaryStage.setScene(new Scene(root, 500, 300));
    primaryStage.setTitle("Programmatically Set Background Color Example");
    primaryStage.show();
  

【讨论】:

【参考方案2】:

找到答案:

            cp.setOnAction(e -> 
            Color c = cp.getValue();
            button.setStyle("-fx-background-color: " + c.toString().replace("0x", "#"));
            System.out.println(c);
        );

【讨论】:

不要将toString() 用于此类功能。 documentation 明确声明它“仅供参考”。使用问题下方评论中链接的问题中的解决方案。【参考方案3】:

当您只需要获取从 JavaFX ColorPicker 生成的颜色值并将其分配给 CSS 属性时,这实际上并没有那么复杂。

在 ColorPicker 的 OnAction 事件中,添加此代码以确保提取前三对十六进制值,然后将它们重新格式化为 CSS 友好格式,如下所示:

String colorString = String.valueOf(colorPicker.getValue());
String regex = "([0-9a-fA-F]2)([0-9a-fA-F]2)([0-9a-fA-F]2)";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(colorString);
StringBuilder cssFormat = new StringBuilder();
if (m.find()) 
    cssFormat.append("#").append(m.group(0)).append(";");

在此示例中,名为 cssFormat 的字符串将能够插入到您需要为其分配的任何 JavaFX 对象的样式中。以下是按照 OP 要求使用 Button 的方法:

if (!cssFormat.isEmpty()) 
  button.setStyle("-fx-background-color: " + cssFormat);

其实就是这么简单。

如果您需要将该字符串转换回颜色,您可以这样做:

Color color = Color.valueOf(colorString);

:-)

【讨论】:

来自 Color.toString 文档:此方法仅供参考。返回字符串的内容和格式可能因实现而异。 ... 或者换句话说:不要出于应用原因使用 toString @kleopatra - 我改了...这样更好吗? no - 错误与第一个版本相同,现在被 String.valueOf 伪装(实现使用..猜猜是什么?)加上模式匹配的一些烟雾。 使用Color#toString() 肯定会更容易,但正如所指出的,文档明确表示输出本质上仅用于调试。尽管我怀疑他们会很快改变实施。但是,我看不出您(失败的)尝试避免#toString() 比接受的(我的)答案更容易/更清楚。如果您不喜欢位操作,那么也许您(或其他人)可以提交功能请求以添加 Color#toHexColorString() 方法,假设此类请求尚不存在。

以上是关于如何在 javaFX 中将颜色从 ColorPicker 转换为 String 值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 11 中将 JavaFX 运行时添加到 Eclipse?

如何在 JavaFX 中将图像设置为按钮的大小

如何在 JavaFX 中将 CheckBox 添加到 TableView

如何在 javafx 中将任何文本或字母转换为图像

推荐颜色选择器实用程序,支持Delphi颜色代码[关闭]

如何在JavaFX中将变换应用于形状?