以前的例子对我有用
为如何在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 项目提出功能请求,并在必要时链接回此答案。