JavaFX changing buttons' color based off input

73 Views Asked by At

I'm currently using javaFX to build a visualization tool. You can see in the image below there are textboxes and green buttons. For every textbox with a 0 shown, it is linked to a specific button beneath it. However, the button is only supposed to turn green if the input value is 1. In case of input 0, the button is supposed to be white; and in case of any other number, an error message is supposed to pop up.

scene builder preview

scene builder

I tried to make a class in Controller.java that would intake the fx:id from scenebuilder but that didn't work. I'm trying to find a way where I am able to use specific names for each textbox because each one is linked to a different button.

1

There are 1 best solutions below

6
SedJ601 On

One thing you can do is create a ChangeListener to handle all the logic. The other is you can create a different ChangeListener for each TextField.

Example of ChangeListener for all TextFields.

import java.util.HashMap;
import java.util.Map;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;

public class App extends Application {
    Map<TextField, Button> nodeMap = new HashMap();    
    
    @Override
    public void start(Stage stage){     
       
        TextField tfOne = new TextField();
        TextField tfTwo = new TextField();
        Button btnOne = new Button("One");
        btnOne.getStyleClass().add("left-arrow");
        Button btnTwo = new Button("Two");
        btnTwo.getStyleClass().add("right-arrow");
    
        nodeMap.put(tfOne, btnOne);
        nodeMap.put(tfTwo, btnTwo);
        
        VBox root = new VBox();
        
        HBox topRoot = new HBox(tfOne, tfTwo);
        topRoot.setSpacing(3);
        
        HBox bottomRoot = new HBox(btnOne, btnTwo);
        bottomRoot.setSpacing(3);        
        
        tfOne.textProperty().addListener(textFieldChangeListener);
        tfTwo.textProperty().addListener(textFieldChangeListener);
        
        root.getChildren().addAll(topRoot, bottomRoot);
        Scene newScene = new Scene(root);
        newScene.getStylesheets().add(getClass().getResource("button_shape.css").toExternalForm());
        stage.setWidth(200);
        stage.setHeight(200);
        stage.setScene(newScene);
        stage.show();
    }

    ChangeListener<String> textFieldChangeListener =    (observable, oldValue, newValue) -> {
                                                            String id;
                                                            
                                                            switch (newValue) {
                                                                case "":
                                                                    id = "";
                                                                    break;
                                                                case "0":
                                                                    id = "button-color-white";
                                                                    break;
                                                                case "1":
                                                                    id = "button-color-green";
                                                                    break;
                                                                default:
                                                                    id = "button-color-red";
                                                            }
                                                            
                                                            TextField key = ((TextField)((StringProperty)observable).getBean());
                                                            nodeMap.get(key).setId(id);                                                            
                                                        };
    
    public static void main(String[] args) {
        launch();
    }
}

CSS

.button{
    -fx-font-size: 16pt;
    -fx-text-fill: white;
    -fx-effect: dropshadow(three-pass-box, black, 10, 0, 0, 0);
}
.right-arrow{
    -fx-shape: "M 224 210 Q 280 210 294 210 Q 294 168 294 168 Q 350 238 350 238 C 350 238 350 224 294 294 C 294 252 294 252 294 252 L 224 252 Z";    
    -fx-background-color: green;
}

.left-arrow{
    -fx-shape: "M 420 210 Q 322 210 322 210 Q 322 210 322 168 Q 280 238 280 238 L 322 294 C 322 252 322 252 322 252 L 420 252 Z";    
    -fx-background-color: green;
}

.up-arrow{
    -fx-shape: "M 322 378 Q 322 294 322 294 Q 322 294 364 294 Q 294 224 294 224 L 224 294 C 266 294 266 294 266 294 L 266 378 Z";
    -fx-background-color: green;
}

.down-arrow{
    -fx-shape: "M 322 294 Q 322 378 322 378 Q 322 378 364 378 Q 294 434 294 434 L 224 378 C 266 378 266 378 266 378 L 266 294 Z";
    -fx-background-color: green;
}

.rectangle{
    -fx-shape: "M 322 294 Q 322 350 322 350 C 210 350 210 350 210 350 L 210 294 Z";
    -fx-background-color: green;
}

#button-color-green{
    -fx-background-color: green;
    -fx-text-fill: white;
}

#button-color-red{
    -fx-background-color: red;
    -fx-text-fill: white;
}

#button-color-white{
    -fx-background-color: white;
    -fx-text-fill: black;
}

Output

enter image description here

Edit after feedback

CSS is not a strong point of mine. This can probably be improved.

  1. Set the stylesheet on the stage.
  2. Set the node's .getStyleClass()
  3. Use the node's setId to alter its style.