JavaFX:弹出窗口的透明度 window 仅改变亮度,仍显示为纯色并隐藏底层舞台

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

我有主要的 window (mainWindow.fxml),我想在上面显示一个透明的弹出窗口 window (errorDialog.fxml),不透明度为 50%,这样window 的主要内容仍然可以在下面看到。 但是,我尝试使 errorDialog.fxml 内的覆盖层背景颜色透明,结果背景颜色显示为纯 50% 灰色,完全隐藏了主要 window。

我尝试在 "overlay" 的样式属性和 controllerErrorDialog.java 的初始化方法中设置透明度。

感谢任何帮助!

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>

您需要确定:

  1. 场景有透明背景,errorScene.setFill(Color.TRANSPARENT);
  2. 舞台透明,使用errorStage.initStyle(StageStyle.TRANSPARENT);
  3. 除根以外的任何内容(您明确想要看透的内容)都具有完全透明的背景

这是一个完整的(虽然不是很用户友好)示例:

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();
    }

}

其中 transparent.css 为:

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

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