代码之家  ›  专栏  ›  技术社区  ›  Joe Mau

从浅绿色到深红色

  •  1
  • Joe Mau  · 技术社区  · 7 年前

    我希望你能看到多少次按钮被按下,我想使这些广告的颜色。 简短解释:浅绿色按钮被按下一次,深红色按钮被按下非常频繁。

    我用一个简单的if解决了这个问题。 γ

    If so (clicksCounter == 1) then green
    

    但这个解决方案不是很优雅,我需要很多如果查询从浅绿色到深红色。现在我的问题是,有人知道一种方法,我如何能流利地将浅绿色变成深红色?

    enter image description here

    我所说的流利,是指从浅绿色到深绿色,再加上“介于两者之间的价值观”,使它看起来更美。

    不像我的例子,只有绿色,黄色和红色,但是颜色的变化应该是平滑的。

    enter image description here enter image description here enter image description here


    主类

    package sample;
    
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    public class Main extends Application {
    
        @Override
        public void start(Stage primaryStage) throws Exception{
            Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
            primaryStage.setTitle("Hello World");
            primaryStage.setScene(new Scene(root, 600, 400));
            primaryStage.show();
        }
    
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    控制器.java

    package sample;
    
    
    import javafx.event.ActionEvent;
    import javafx.event.EventHandler;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Button;
    import javafx.scene.control.DateCell;
    import javafx.scene.control.DatePicker;
    import javafx.scene.control.Label;
    
    import javax.security.auth.callback.Callback;
    import java.net.URL;
    import java.time.LocalDate;
    import java.util.Date;
    import java.util.ResourceBundle;
    
    public class Controller implements Initializable {
    
        private int clicksCounter = 0;
        private String date = String.valueOf(LocalDate.now().getDayOfMonth());
    
        @FXML
        private Button button2;
    
        @FXML
        private DatePicker datePicker;
    
        @FXML
        private Label lbColor;
    
        @Override
        public void initialize(URL location, ResourceBundle resources) {
            button2.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    System.out.println(clicksCounter);
                    clicksCounter++;
                    if(clicksCounter == 1 ) {
                        lbColor.setStyle("-fx-background-color: #04b404;");
                    }
                    else if(clicksCounter == 2) {
                        lbColor.setStyle("-fx-background-color: #ffff13;");
                    }
                    else {
                        lbColor.setStyle("-fx-background-color: #df0101;");
                    }
    
                }
            });
    
            javafx.util.Callback<DatePicker, DateCell> set = new javafx.util.Callback<DatePicker, DateCell>() {
                @Override
                public DateCell call(final DatePicker datePicker) {
                    return new DateCell() {
                        @Override public void updateItem(LocalDate item, boolean empty) {
                            super.updateItem(item, empty);
                            //if today, change text and style
                            if (item.equals(LocalDate.now())) {
                                setText(date +"/" + clicksCounter);
                                if(clicksCounter == 1 ) {
                                    setStyle("-fx-background-color: #04b404;");
                                }
                                else if(clicksCounter == 2) {
                                    setStyle("-fx-background-color: #ffff13;");
                                }
                                else {
                                    setStyle("-fx-background-color: #df0101;");
                                }
                            }
                        }
                    };
                }
            };
            datePicker.setDayCellFactory(set);
    
    
        }
    }
    

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.DatePicker?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.layout.AnchorPane?>
    
    <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
       <children>
          <Button fx:id="button2" layoutX="280.0" layoutY="48.0" mnemonicParsing="false" text="Click" />
          <DatePicker fx:id="datePicker" layoutX="45.0" layoutY="56.0" />
          <Label fx:id="lbColor" layoutX="191.0" layoutY="155.0" text="Color" />
       </children>
    </AnchorPane>
    

    提前谢谢你。

    2 回复  |  直到 7 年前
        1
  •  1
  •   c0der    7 年前

    您可以基于这些颜色的RGB值实现一个简单的解决方案:

    green  in rgb is (0,  255, 0)
    yellow in rgb is (255,255, 0)
    red in rgb is (255, 0 , 0)

    所以你从绿色开始,增加红色直到你变黄,然后减少绿色直到你变红:

    public class Controller implements Initializable {
    
        //defines the incremental change in color 
        private static final int COLOR_INCREMENT = 30;
        //initial rgb values (green) 
        private int red = 0, green = 255, blue = 0;
        @FXML
        private Button button2;
    
        @FXML
        private DatePicker datePicker;
    
        @FXML
        private Label lbColor;
    
        @Override
        public void initialize(URL location, ResourceBundle resources) {
            button2.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    lbColor.setStyle("-fx-background-color:"+ getColorString()+";");
                }
    
            });
            //Cell factory omitted. Not needed to demonstrate the question nor the answer 
        }
    
        //increment color by COLOR_INCREMENT to step from green to yellow to red 
        //and return string representation of it 
        //green is rgb is (0, 255, 0)
        //yellow rgb is (255, 255, 0)
        //red in rgb is (255, 0, 0)
        private String getColorString() {
    
            if((green == 255) && (red < 255)) {
                red = (red + COLOR_INCREMENT) > 255 ?  255 : (red + COLOR_INCREMENT) ;
            }else if( (red == 255) && (green > 0)){
                green = (green - COLOR_INCREMENT) < 0 ?  0 : (green - COLOR_INCREMENT) ;
            }
    
            StringBuilder sb = new StringBuilder("rgb(");
            sb.append(red).append(",")
            .append(green).append(",")
            .append(blue).append(")");
    
            return sb.toString();
        }
    }
    

    请注意,更改的次数是有限的,并由颜色增量的大小定义。2次(255/颜色增量)后,颜色保持红色。
    它可以进一步改进,克服这一限制。它还可以从动态(变化)颜色增量中受益。

    编辑 你当然可以用同样的方法来改变 DateCell 颜色:

    @Override
    public void initialize(URL location, ResourceBundle resources) {
    
        button2.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                lbColor.setStyle("-fx-background-color:"+ getColorString()+";");
            }
    
        });
    
        javafx.util.Callback<DatePicker, DateCell> set = new javafx.util.Callback<DatePicker, DateCell>() {
            @Override
            public DateCell call(final DatePicker datePicker) {
                return new DateCell() {
                    @Override public void updateItem(LocalDate item, boolean empty) {
                        super.updateItem(item, empty);
                        //if today, change text and style
                        if (item.equals(LocalDate.now())) {
                            setText(date +"/" + clicksCounter);
                            setStyle("-fx-background-color: "+ getColorString () +"; ");
                        }
                    }
                };
            }
        };
        datePicker.setDayCellFactory(set);
    }
    

    注意呼叫 getColorString () 两次(一次由按钮处理程序执行,一次由单元格工厂执行)会导致颜色更改两次。
    为了防止它,你可以设置一个颜色字段。该字段由按钮处理程序更新,并由 Label 以及电池工厂:

    public class Controller implements Initializable {
    
        protected static final int COLOR_INCREMENT = 30;
    
        @FXML
        private Button button2;
    
        @FXML
        private DatePicker datePicker;
    
        @FXML
        private Label lbColor;
    
        private int red = 0, green = 255, blue = 0;
        private String colorAsString; //string representation of rgb color 
        private int clicksCounter = 0;
        private String date = String.valueOf(LocalDate.now().getDayOfMonth());
    
        @Override
        public void initialize(URL location, ResourceBundle resources) {
    
            button2.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    colorAsString = getColorString();
                    lbColor.setStyle("-fx-background-color:"+ colorAsString +";");
                }
            });
    
            javafx.util.Callback<DatePicker, DateCell> set = new javafx.util.Callback<DatePicker, DateCell>() {
                @Override
                public DateCell call(final DatePicker datePicker) {
                    return new DateCell() {
                        @Override public void updateItem(LocalDate item, boolean empty) {
                            super.updateItem(item, empty);
                            //if today, change text and style
                            if (item.equals(LocalDate.now())) {
                                setText(date +"/" + clicksCounter);
                                setStyle("-fx-background-color: "+ colorAsString +"; ");
                            }
                        }
                    };
                }
            };
            datePicker.setDayCellFactory(set);
        }
    
        //increment color by COLOR_INCREMENT to step from green to yellow to red
        //and return string representation of it
        //green is rgb is (0, 255, 0)
        //yellow rgb is (255, 255, 0)
        //red in rgb is (255, 0, 0)
        private String getColorString() {
    
            if((green == 255) && (red < 255)) {
                red = (red + COLOR_INCREMENT) > 255 ?  255 : (red + COLOR_INCREMENT) ;
            }else if( (red == 255) && (green > 0)){
                green = (green - COLOR_INCREMENT) < 0 ?  0 : (green - COLOR_INCREMENT) ;
            }
    
            StringBuilder sb = new StringBuilder("rgb(");
            sb.append(red).append(",")
            .append(green).append(",")
            .append(blue).append(")");
    
            return sb.toString();
        }
    }
    
        2
  •  2
  •   Jai    7 年前

    Color 实现 Interpolatable<Color> 接口,以便api可以为您进行插值。

    public class Controller implements Initializable {
        private static final Color GREEN = Color.web("#04b404");
        private static final Color YELLOW = Color.web("#ffff13");
        private static final Color RED = Color.web("#df0101");
    
        private static final double INCREMENT_STEP = 0.3d; // Adjust this
    
        private final DoubleProperty step = new SimpleDoubleProperty();
        private final ObjectBinding<Color> backgroundColor;
    
        public Controller {
            backgroundColor = Bindings.createObjectBinding(() -> {
                final double value = step.get() % 3.0; // We get modulus so that 0 <= value < 3
    
                switch((int) value) { // We will round down the value
                    case 0:
                        return GREEN.interpolate(YELLOW, value % 1.0); // Get an interpolate value of 0.0-1.0
                    case 1:
                        return YELLOW.interpolate(RED, value % 1.0);
                    case 2:
                        return RED.interpolate(GREEN, value % 1.0);
                    default:
                        return null; // Shouldn't happen at all
                }
            }, step);
        }
    
        @Override
        public void initialize(URL location, ResourceBundle resources) {
            button2.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    step.set(step.get() + INCREMENT_STEP);
                }
            });
    
            javafx.util.Callback<DatePicker, DateCell> set = new javafx.util.Callback<DatePicker, DateCell>() {
                @Override
                public DateCell call(final DatePicker datePicker) {
                    return new DateCell() {
                        @Override public void updateItem(LocalDate item, boolean empty) {
                            super.updateItem(item, empty);
                            //if today, change text and style
                            if (item.equals(LocalDate.now())) {
                                setText(date +"/" + clicksCounter); // Not sure if you still need the click count
                                backgroundProperty().bind(Bindings.when(
                                        backgroundColor.isNotNull())
                                    .then(Bindings.createObjectBinding(() -> 
                                        new Background(new BackgroundFill(
                                            backgroundColor.get(),
                                            CornerRadii.EMPTY,
                                            Insets.EMPTY
                                        )), backgroundColor)
                                    ).otherwise(Background.EMPTY)
                                );
                            }
                        }
                    };
                }
            };
            datePicker.setDayCellFactory(set);
        }
    }