Varest
Varest

Reputation: 57

JavaFX: transparency of popup window only changes brightness, still displays as solid color and hides underlying stage

I have the main window (mainWindow.fxml) on top of which I want to display a transparent popup window (errorDialog.fxml) with 50% opacity so that the main window's content can still be seen underneath. However, my attempts at making the background colour of overlay inside errorDialog.fxml transparent only results in the background colour being displayed as a solid 50% grey that hides the main window completely.

I tried to set the transparency both in the style attribute of "overlay" as well as in in the initialize method of controllerErrorDialog.java.

Any help is appreciated!

controllerMainWindow.java

package myPackage;
import [...];

public class controllerMainWindow extends AbstractController
{

    @FXML
    private Button btnOpenPopup;
    @FXML
    private BorderPane paneMainWindow;
    //---------------------------------------------------------------------------------------------------
    public void initialize()
    {
    }
    //---------------------------------------------------------------------------------------------------
    @FXML
    public void handleButtonAction(ActionEvent event)
    {
        try {
             if (event.getSource().equals(btnOpenPopup)) {
                FXMLLoader errorLoader = new FXMLLoader();
                errorLoader.setLocation(getClass().getResource("errorDialog.fxml"));
                controllerErrorDialog errorController = new controllerErrorDialog();
                errorLoader.setController(errorController);
                Parent layout;
                layout = errorLoader.load();
                Scene errorScene = new Scene(layout);
                Stage errorStage = new Stage();
                errorStage.initStyle(StageStyle.UNDECORATED);
                errorStage.setMaximized(true);
                errorController.setStage(errorStage);
                if(this.main!=null) {
                    errorStage.initOwner(main.getPrimaryStage());
                }
                errorStage.initModality(Modality.APPLICATION_MODAL);
                errorStage.setScene(errorScene);
                errorStage.showAndWait();
            } 
        }catch (IOException exceptionCockpitSettings) {
            System.out.println("Error when switching to cockpitSettings.");
            exceptionCockpitSettings.printStackTrace();
            return;
        } 
    }
    //---------------------------------------------------------------------------------------------------
}

controllerErrorDialog.java

package myPackage;
import [...];

public class controllerErrorDialog extends AbstractController implements Initializable
{
    @FXML
    private BorderPane overlay;
    private Stage stage = null;
//-------------------------------------------------------------------------------------------------------
    @Override
    public void initialize(URL url, ResourceBundle rb)
    {
        overlay.setStyle("fx-background-color: transparent");
    }
    //---------------------------------------------------------------------------------------------------
    public void setStage(Stage stage) {
        this.stage = stage;
    }
    //---------------------------------------------------------------------------------------------------
}

errorDialog.fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import [...]?>

<BorderPane fx:id="overlay" prefWidth="1920" prefHeight="1080" style="-fx-background-color: rgba(0,0,0,0.5)" xmlns:fx="http://javafx.com/fxml">
   <top></top>
   <left></left>
   <center></center>
   <right></right>
   <bottom></bottom>
</BorderPane>

Upvotes: 0

Views: 939

Answers (1)

James_D
James_D

Reputation: 209553

You need to make sure:

  1. The scene has a transparent background, with errorScene.setFill(Color.TRANSPARENT);
  2. The stage is transparent, using errorStage.initStyle(StageStyle.TRANSPARENT);
  3. Any content (that you explicitly want to see through) other than the root has fully transparent background

Here's a complete (albeit not very user-friendly) example:

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Random;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

/**
 * JavaFX App
 */
public class App extends Application {

    private Random rng = new Random();

    @Override
    public void start(Stage stage) {
        Button createError = new Button("Try something dangerous");
        createError.setOnAction(e -> {
            try {
                throw new Exception("Boom!");
            } catch (Exception exc) {
                BorderPane root = new BorderPane();
                root.setTop(new Label("Error"));
                Label stackTrace = new Label();
                StringWriter sw = new StringWriter();
                exc.printStackTrace(new PrintWriter(sw));

                ScrollPane scroller = new ScrollPane(stackTrace);
                stackTrace.setText(sw.toString());
                root.setCenter(scroller);

                Button close = new Button("Close");
                HBox buttons = createHBox(close);
                root.setBottom(buttons);

                Scene errorScene = new Scene(root, 400, 400);
                errorScene.setFill(Color.TRANSPARENT);
                errorScene.getStylesheets().add(getClass().getResource("transparent.css").toExternalForm());
                Stage errorStage = new Stage();

                close.setOnAction(evt -> errorStage.close());

                errorStage.setScene(errorScene);
                errorStage.initStyle(StageStyle.TRANSPARENT);
                errorStage.initModality(Modality.APPLICATION_MODAL);
                errorStage.initOwner(stage);
                errorStage.show();
            }
        });

        HBox buttons = createHBox(createError);
        BorderPane root = new BorderPane(createContent());
        root.setBottom(buttons);


        Scene scene = new Scene(root, 600, 600);
        stage.setScene(scene);
        stage.show();
    }

    private HBox createHBox(Node... content) {
        HBox buttons = new HBox(content);
        buttons.setAlignment(Pos.CENTER);
        buttons.setPadding(new Insets(2));
        return buttons;
    }

    private Node createContent() {
        Pane pane = new Pane();
        for (int i = 0 ; i < 15 ; i++) {
            Circle circle = new Circle(
                    50 + rng.nextDouble() * 500, 
                    50 + rng.nextDouble() * 500, 
                    50 + rng.nextDouble() * 50, 
                    randomColor());
            pane.getChildren().add(circle);
        }
        return pane ;
    }

    private Color randomColor() {
        return Color.color(rng.nextDouble(), rng.nextDouble(), rng.nextDouble(), 0.5 + 0.25 * rng.nextDouble());
    }

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

}

with transparent.css being:

.root {
  -fx-background-color: #ffffff7f ;
}

.root HBox, .root .scroll-pane, .root .scroll-pane .viewport {
  -fx-background-color: transparent ;
}

enter image description here

Upvotes: 4

Related Questions