8

我试图让我的窗格在视觉上更好一点,所以,我正在做的是:将我的舞台设置为 UNDECORATED(OK)和(TRYING)以添加阴影效果(NOT OK)。

我发现了一些类似的案例,但没有一个工作:在 javafx 2.0 中创建未装饰的舞台如何在 JavaFX 中向窗口添加阴影?.

似乎没有设置阴影。我不明白为什么。

这就是我所拥有的:

public static int showConfirmDialog(Window father, String title, String body, String[]      msgBtn) 
{
    System.out.println("La vai eu");
    AnchorPane ap = createPaneWithButton(2, msgBtn,body);
    
    ap.setEffect(initDropShadow());
    Scene scene = new Scene(ap);
    
    Stage stage = new Stage();
    
    stage.setTitle(title);
    
    scene.setFill(null);
    stage.initStyle(StageStyle.TRANSPARENT);
    
    
    stage.setScene(scene);
    stage.initStyle(StageStyle.UNDECORATED);
    stage.show();
    
    return 1;
}

private static AnchorPane createPaneWithButton(int qtBtn, String[] msgsBtn, String body) {
    AnchorPane ap = createPane();
    HBox laneBtn = new HBox(30);
    VBox vbox = new VBox(20);
    
    BorderPane layout = new BorderPane();
    
    Button btn;
    
    for(int i = 0; i < qtBtn; i++ ){
        btn = new Button();
        btn.setText(msgsBtn[i]);
        
        laneBtn.getChildren().add(btn);
    }
    
    vbox.getChildren().add(new Text(body));
    vbox.getChildren().add(laneBtn);
    
    layout.setCenter(vbox);
    
    ap.getChildren().add(layout);
    
    return ap;
}

private static AnchorPane createPane() {
    AnchorPane ap = new AnchorPane();
    
    ap.setLayoutX(250);
    ap.setLayoutY(50);
    
    return ap;
}
4

4 回答 4

12

以前的例子对我有用

为如何在JavaFX中向窗口添加阴影?在 Java 8b96、Windows 7 上对我来说效果很好(在可见的对话框上投影)。当我为 JavaFX 2 编写它时,它也可以在那个环境中工作。

由于您没有提供完整的可执行代码,因此我无法准确说明您在示例中缺少什么。

透明对话框

您的代码可能存在的问题

我的猜测是您没有插入背景内容,以便对话框中有空间显示阴影。也就是说,您正在用内容填充对话框,而不是在对话框中围绕内容留出空间来显示效果。下面的例子用css规则实现了插入-fx-background-insets: 12;

更新的示例代码

我将示例代码的修改版本复制到了这个答案中,这样它就不仅仅包含在另一个答案的晦涩要点链接中。修改将仅使用标准 API 调用,因为自创建原始答案以来,原始答案中使用的构建器已被弃用。

ModalConfirmExample.java

import javafx.application.Application;
import javafx.beans.value.*;
import javafx.concurrent.Worker;
import javafx.event.*;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.effect.BoxBlur;
import javafx.scene.effect.Effect;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.web.WebView;
import javafx.stage.Modality;
import javafx.stage.*;

/**
 * Application modal dialog with the following properties:
 *   translucent background
 *   drop-shadowed border
 *   non-rectangular shape
 *   blur effect applied to parent when dialog is showing
 *   configurable message text
 *   configurable yes and no event handlers
 */
class ModalDialog extends Stage {
    private static final Effect parentEffect = new BoxBlur();

    private final String messageText;
    private final EventHandler<ActionEvent> yesEventHandler;
    private final EventHandler<ActionEvent> noEventHandler;

    public ModalDialog(
            Stage parent,
            String messageText,
            EventHandler<ActionEvent> yesEventHandler,
            EventHandler<ActionEvent> noEventHandler) {
        super(StageStyle.TRANSPARENT);

        this.messageText = messageText;
        this.yesEventHandler = yesEventHandler;
        this.noEventHandler = noEventHandler;

        // initialize the dialog
        initOwner(parent);
        initParentEffects(parent);
        initModality(Modality.APPLICATION_MODAL);
        setScene(createScene(createLayout()));
    }

    private StackPane createLayout() {
        StackPane layout = new StackPane();
        layout.getChildren().setAll(
                createGlassPane(),
                createContentPane()
        );

        return layout;
    }

    private Pane createGlassPane() {
        final Pane glassPane = new Pane();
        glassPane.getStyleClass().add(
                "modal-dialog-glass"
        );

        return glassPane;
    }

    private Pane createContentPane() {
        final HBox contentPane = new HBox();
        contentPane.getStyleClass().add(
                "modal-dialog-content"
        );
        contentPane.getChildren().setAll(
                new Label(messageText),
                createYesButton(),
                createNoButton()
        );

        return contentPane;
    }

    private Button createYesButton() {
        final Button yesButton = new Button("Yes");
        yesButton.setDefaultButton(true);
        yesButton.setOnAction(yesEventHandler);

        return yesButton;
    }

    private Button createNoButton() {
        final Button noButton = new Button("No");
        noButton.setOnAction(noEventHandler);

        return noButton;
    }

    private Scene createScene(StackPane layout) {
        Scene scene = new Scene(layout, Color.TRANSPARENT);
        scene.getStylesheets().add(
                getClass().getResource(
                        "modal-dialog.css"
                ).toExternalForm()
        );

        return scene;
    }

    private void initParentEffects(final Stage parent) {
        this.showingProperty().addListener(new ChangeListener<Boolean>() {
            @Override public void changed(ObservableValue<? extends Boolean> observableValue, Boolean wasShowing, Boolean isShowing) {
                parent.getScene().getRoot().setEffect(
                        isShowing ? parentEffect : null
                );
            }
        });
    }
}

/**
 * Demonstrates a modal confirm box in JavaFX.
 * Dialog is rendered upon a blurred background.
 * Dialog is translucent.
 */
public class ModalConfirmExample extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(final Stage primaryStage) {
        final WebView webView = new WebView();

        final ModalDialog dialog = createWebViewPreferenceDialog(primaryStage, webView);

        // show the preference dialog each time a new page is loaded.
        webView.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
            @Override
            public void changed(ObservableValue<? extends Worker.State> observableValue, Worker.State state, Worker.State newState) {
                if (newState.equals(Worker.State.SUCCEEDED)) {
                    dialog.show();
                    dialog.toFront();
                }
            }
        });
        webView.getEngine().load("http://docs.oracle.com/javafx/");

        // initialize the stage
        primaryStage.setTitle("Modal Confirm Example");
        primaryStage.setScene(new Scene(webView));
        primaryStage.show();
    }

    private ModalDialog createWebViewPreferenceDialog(final Stage primaryStage, final WebView webView) {
        final EventHandler<ActionEvent> yesEventHandler =
                new EventHandler<ActionEvent>() {
                    @Override public void handle(ActionEvent actionEvent) {
                        System.out.println("Liked: " + webView.getEngine().getTitle());
                        primaryStage.getScene().getRoot().setEffect(null);
                        Stage dialogStage = getTargetStage(actionEvent);
                        dialogStage.close();
                    }
                };

        final EventHandler<ActionEvent> noEventHandler =
                new EventHandler<ActionEvent>() {
                    @Override public void handle(ActionEvent actionEvent) {
                        System.out.println("Disliked: " + webView.getEngine().getTitle());
                        primaryStage.getScene().getRoot().setEffect(null);
                        Stage dialogStage = getTargetStage(actionEvent);
                        dialogStage.close();
                    }
                };

        return new ModalDialog(primaryStage, "Will you like this Page?", yesEventHandler, noEventHandler);
    }

    private Stage getTargetStage(ActionEvent actionEvent) {
        Node target = (Node) actionEvent.getTarget();
        return ((Stage) target.getScene().getWindow());
    }
}

模态对话框.css

.root {
  -fx-opacity: 0.9;
}

.modal-dialog-glass {
  -fx-effect: dropshadow(three-pass-box, derive(cadetblue, -20%), 10, 0, 4, 4); 
  -fx-background-color: derive(cadetblue, -20%); 
  -fx-background-insets: 12; 
  -fx-background-radius: 6;
}

.modal-dialog-content {
  -fx-padding: 20;
  -fx-spacing: 10;
  -fx-alignment: center;
  -fx-font-size: 20;
  -fx-background-color: linear-gradient(to bottom, derive(cadetblue, 20%), cadetblue);
  -fx-border-color: derive(cadetblue, -20%);
  -fx-border-width: 5;
  -fx-background-insets: 12;
  -fx-border-insets: 10;
  -fx-border-radius: 6;
  -fx-background-radius: 6;
}

改用库

另请注意,对于创建对话框,我强烈建议使用ControlsFX项目,而不是创建您自己的对话框系统。如果 ControlsFX 缺少您需要的功能(例如投影支持),您可以针对 ControlsFX 项目提出功能请求,并在必要时链接回此答案。

于 2013-07-10T19:46:30.790 回答
6

简单的工作示例。

第一个结果示例 第二个结果示例

这是fxml结构:

AnchorPane(200,200) // pane for space for shadow
    \- AnchorPane(center) // appliction pane
         \- Label // application content

真实screen.fxml

<AnchorPane fx:id="shadowPane" prefHeight="200.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <AnchorPane fx:id="rootPane" layoutX="56.0" layoutY="62.0">
         <children>
            <Label fx:id="someLabel" layoutX="30.0" layoutY="30.0" text="Label" textFill="#f20000" />
         </children>
         <padding>
            <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
         </padding>
      </AnchorPane>
   </children>
</AnchorPane>

Main.java

@Override
public void start(Stage stage) throws Exception {
    FXMLLoader loader = new FXMLLoader(getClass().getResource("/sample/screen.fxml"));
    AnchorPane shadowPane = loader.load();
    AnchorPane rootPane = (AnchorPane) shadowPane.lookup("#rootPane");
    rootPane.setStyle("-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.4), 10, 0.5, 0.0, 0.0);" +
                      "-fx-background-color: white;"); // Shadow effect

    Scene scene = new Scene(shadowPane);
    stage.setScene(scene);

    shadowPane.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID, null, null))); // Some borders for for clarity

    shadowPane.setStyle("-fx-background-color: transparent;"); // Makes shadowPane transparent
    scene.setFill(Color.TRANSPARENT); // Fill our scene with nothing
    stage.initStyle(StageStyle.TRANSPARENT); // Important one!
    stage.show();
}
于 2015-07-28T21:12:15.707 回答
1

好吧,我找到了一个非常简单的解决方案。也许这在早期版本中不受支持?但是..代码:

iconPane.setEffect(new DropShadow(2d, 0d, +2d, Color.BLACK));

图片显示了结果 - 我的意图是在FAB的外观中显示一个图标

在此处输入图像描述

于 2015-05-14T00:02:24.900 回答
0

没有 FXML 的舞台阴影:

public void start(Stage stage){
    final double RADIUS = 5;
    VBox rootNode = new VBox();
    Insets bgInsets = new Insets(RADIUS);
    BackgroundFill bgFill = new BackgroundFill(Color.PINK, null, bgInsets);
    rootNode.setBackground(new Background(bgFill));
    DropShadow dropShadow = new DropShadow(RADIUS, Color.GRAY);
    rootNode.setEffect(dropShadow);

    Scene scene = new Scene(rootNode);
    scene.setFill(Color.TRANSPARENT);
    stage.setScene(scene);
    stage.initStyle(StageStyle.TRANSPARENT);
    stage.show();
}
于 2019-12-09T15:18:28.483 回答