Search code examples
javafx-8rounded-corners

javafx rounded rectangle corners


When you create a rounded VBox in JavaFX, and the background color for the VBox is black, assume the rounded corners after filling the button is white, How can I fill this region with another color (Assume I want it to be totally transparent).


Solution

  • I assume, the questioneer wants to finally hava a floating round VBox. This can probably be achieved in many ways, without thinking to much about it, I would rather make use of a clipping Node instead of a pure CSS approach (which should be doable as well).

    As he already wrote, you would also need to make the Scenes fill Color.TRANSPARENT (and probably the Stage as well).

    My approach looks like this. First the FXML file:

    <?import java.lang.*?>
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.control.TextField?>
    <?import javafx.scene.layout.BorderPane?>
    <?import javafx.scene.layout.VBox?>
    
    <BorderPane xmlns:fx="http://javafx.com/fxml" fx:id="root" fx:controller="application.ClipExampleController" style="-fx-background-color: steelblue;">
    
        <center>
            <VBox fx:id="vbox" alignment="CENTER" spacing="5" maxWidth="150"> 
                <Label text="Bla"/> 
                <TextField promptText="Blub"/> 
                <Button text="Do it"/> 
            </VBox>
        </center>
    </BorderPane>
    

    Then the Controller class: package application;

    import javafx.beans.binding.DoubleBinding;
    import javafx.fxml.FXML;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.VBox;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.Circle;
    
    public class ClipExampleController {
    
        @FXML
        private BorderPane root;
        @FXML
        private VBox vbox;
    
        @FXML
        protected void initialize() {
    
            Circle clip = new Circle();
            clip.radiusProperty().bind(new DoubleBinding() {
                {
                    bind(vbox.widthProperty());
                }
    
                @Override
                protected double computeValue() {
                    return vbox.getWidth() / 2 + 25;
                }
            });
            clip.centerXProperty().bind(new DoubleBinding() {
                {
                    bind(root.widthProperty());
                }
    
                @Override
                protected double computeValue() {
                    return root.getWidth() / 2;
                }
            });
            clip.centerYProperty().bind(new DoubleBinding() {
                {
                    bind(root.heightProperty());
                }
    
                @Override
                protected double computeValue() {
                    return root.getHeight() / 2;
                }
            });
            root.setClip(clip);
        }
    }
    

    and finally the glue code - the main Application: package application;

    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.scene.paint.Color;
    import javafx.stage.Stage;
    import javafx.stage.StageStyle;
    
    public class Main extends Application {
        @Override
        public void start(Stage stage) throws Exception {
    
            FXMLLoader loader = new FXMLLoader(getClass().getResource("ClipExample.fxml"));
            Parent root = loader.load();
            Scene scene = new Scene(root, 300, 300);
    
            scene.setFill(Color.TRANSPARENT);
            stage.initStyle(StageStyle.TRANSPARENT);
    
            stage.setScene(scene);
            stage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    So. Assuming, that I understand you correctly, this would be my solution.