-1

Modify the color of a JavaFX button so it gets darker when I pass the mouse, but when it is decorated with CSS:

When you modify the color of a Button in JavaFX, you lose the effect that makes it darker when the mouse passes. So seeing that we get 2 functions to do some action when the mouse gets over the button setOnMouseEntered/setOnMouseExited I can just get the color and use the function .darker()like this:

    private Color last_color = null;
    public void change_color(Button button) {
        Color color;
        if (last_color == null) {
            color = (Color)button.getBackground().getFills().get(0).getFill();
            last_color = color;
            color = color.darker();
        } else {
            color = last_color;
            last_color = null;
        }

        button.setBackground(new Background(new BackgroundFill(color, CornerRadii.EMPTY, Insets.EMPTY)));
    }

This actually works, except when the color of the buttons is in CSS, looks like the CSS style is beyong the background color set with Java code.

The buttons are probably going to be styled with CSS, and I would like to have a generic function to work in any Button. Is possible to get the color from CSS and modify it?

If not, how could I make the Button darker when the mouse is over it?

  • Are there any limitations, in changing the color of button using CSS only? like using `:hover` psuedo class – Sai Dandem Nov 20 '22 at 22:28
  • unrelated: stick to java naming conventions (no underscores) – kleopatra Nov 20 '22 at 23:06
  • *"Is possible to get the color from CSS and modify it?"*, you can override a [looked-up color](https://openjfx.io/javadoc/19/javafx.graphics/javafx/scene/doc-files/cssref.html#typecolor) by setting its value on the node (e.g. `button.setStyle("-fx-base: tomato");`), this can also be done via [setting a stylesheet in code](https://stackoverflow.com/questions/24704515/in-javafx-8-can-i-provide-a-stylesheet-from-a-string/69234685#69234685) which defines or overrides the looked-up color. – jewelsea Nov 21 '22 at 22:11
  • You can query the CSS metadata using the [`Styleable`](https://openjfx.io/javadoc/19/javafx.graphics/javafx/css/Styleable.html) interface, but that might not help you much. Getting the color from CSS can be ambiguous as CSS defines cascading rules which apply at runtime to define the actual styling used on a node. – jewelsea Nov 21 '22 at 22:22

1 Answers1

4

To change the color of the button on hover, you can add the corresponding css in the CSS file.

.myButton:hover{
    -fx-color: derive(-fx-base, -45%);
}

But if you say, you need to do some calculations, or other logic to determine the color, then you see the below approach.The below approach is to give you some idea only. THIS IS NOT A SOLUTION. I always recommend to get things done using CSS.

The key point to note is : the background of a button is made up of many fills. You need to know which fill you need to modify.

enter image description here

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.List;

public class ButtonBackgroundDemo extends Application {

    public static void main(String[] args) {
        launch(args);
    }
    BackgroundFill lastFill;
    @Override
    public void start(Stage primaryStage) {
        Button button = new Button("Api Test");
        button.addEventFilter(MouseEvent.MOUSE_ENTERED, e->changeColor(button, e));
        button.addEventFilter(MouseEvent.MOUSE_EXITED, e->changeColor(button, e));

        Button button2 = new Button("Css Test");
        button2.getStyleClass().add("myButton");

        VBox root = new VBox(button,button2);
        root.setAlignment(Pos.CENTER);
        root.setSpacing(20);
        Scene scene = new Scene(root, 200, 200);
        scene.getStylesheets().add(getClass().getResource("button.css").toExternalForm());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * I really think this is an overkill. Instead, use CSS implementation
     */
    private void changeColor(Button button, MouseEvent e) {
        int fillSize = button.getBackground().getFills().size();
        List<BackgroundFill> fills = new ArrayList<>();
        button.getBackground().getFills().forEach(fills::add);
        if(e.getEventType() == MouseEvent.MOUSE_ENTERED){
            lastFill = fills.get(fillSize-1);
            fills.remove(lastFill);
            // Use your logic to darken the lastFill.getFill(). This may be Linear-Gradient as well. so get the correct color from gradient as well.
            BackgroundFill fill = new BackgroundFill(Color.DARKGREY, lastFill.getRadii(),lastFill.getInsets());
            fills.add(fill);
        }else {
            fills.remove(fillSize-1);
            fills.add(lastFill);
        }
       button.setBackground(new Background(fills,null));
    }
}

And in the button.css:

.myButton:hover{
    -fx-color: derive(-fx-base, -45%);
}
Sai Dandem
  • 8,229
  • 11
  • 26