JavaFX Tutorials

Saturday, July 16, 2016

Windows Hack for JavaFX UNDECORATED Stages

Stages initialized with StageStyle.UNDECORATED display a shadow on the Mac and Linux, making the custom window standout from the apps running in the background.  On Windows, UNDECORATED does not display a shadow, so if the window is a light color, it may bleed into the background if there is no border.

This hack wraps up the Parent from an FXML file into a VBox.  A DropShadow is added to the Parent ("your content") and the VBox is padded to allow for the DropShadow display.  Then both the Scene and the VBox are set to be completely transparent.

The StageStyle for this Windows hack must be TRANSPARENT.



Here is the code for the Windows hack.


public class WindowsHack {

    public Scene getShadowScene(Parent p) {
        Scene scene;
        VBox outer = new VBox();
        outer.getChildren().add( p );
        outer.setPadding(new Insets(10.0d));
        outer.setBackground( new Background(new BackgroundFill( Color.rgb(0,0,0,0), new CornerRadii(0), new
                Insets(0))));

        p.setEffect(new DropShadow());
        ((VBox)p).setBackground( new Background(new BackgroundFill( Color.WHITE, new CornerRadii(0), new Insets(0)
        )));

        scene = new Scene( outer );
        scene.setFill( Color.rgb(0,255,0,0) );
        return scene;
    }
}

Here is a sample program that applies the Windows hack and must be called with the Stage set to TRANSPARENT. If the app is not running on Windows, then the hack is skipped and the Stage is initialized to UNDECORATED.
public class FlatWinApp extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

        Parent p = FXMLLoader.load( FlatWinApp.class.getResource("/part3/finish/FlatWin.fxml"));

        Scene scene = null;

        String osName = System.getProperty("os.name");
        if( osName != null && osName.startsWith("Windows") ) {

            //
            // Windows hack b/c unlike Mac and Linux, UNDECORATED doesn't include a shadow
            //
            scene = (new WindowsHack()).getShadowScene(p);
            primaryStage.initStyle(StageStyle.TRANSPARENT);

        } else {
            scene = new Scene( p );
            primaryStage.initStyle(StageStyle.UNDECORATED);
        }

        scene.getStylesheets().add("part3/finish/fw.css");

        primaryStage.setTitle("flatwinapp");
        primaryStage.setScene( scene );
        primaryStage.setMinHeight(200.0d);
        primaryStage.setMinWidth(300.0d);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

If you'd like to see more of this custom window code, check out the 3-part course on Bekwam Courses.

1 comment: