在我正在开发的 JavaFX 程序中,我有一个 StackPane。第一个 child 是一个 BorderPane,里面有其他东西。
我希望能够显示弹出窗口,使弹出窗口以外的所有内容变暗,以创建额外的焦点。这就是为什么我创建了一个扩展 StackPane 的“DarkenStackPane”。在创建时(在构造函数中),它向其子项添加一个不透明度为 0.0 的矩形。它有两个函数,darken() 和 brighten()。 darken() 有一个从 0.0 到 0.5 的 FadeTransition,brighten() 相反。
我向 StackPane 添加了一个 Pane,这调用了 darken() 函数。 darken() 函数首先将黑色 Rectangle 置于前面,然后将 Pane 置于前面。
它工作正常,但 StackPane 会调整其所有子项的大小以适合其大小……我不希望这种情况发生。相反,我希望具有自己的宽度和高度的弹出 Pane 在 StackPane 中居中。
我知道我可以使用 StackPane.setMargin(它适用于硬编码值),但我无法确定正确的边距,因为在创建时 Pane 还没有父级。
当您的 Pane 添加到父级时,是否会调用任何方法?
我尝试使用 ChangeListener 执行此操作,但我无法在匿名函数中绑定(bind)属性。
最佳答案
考虑使用 ControlsFX
ControlsFX库有一个称为“轻量级对话框”的功能,它执行相同的对话框覆盖效果。为此类解决方案使用预构建的库通常比滚动您自己的实现更好。
如果您选择推出自己的解决方案而不是使用 ControlsFX,请继续阅读。 . .
解决方案
放置您的 StackPane 的叠加子 Pane 在Group .
StackPane stack = new StackPane(mainPane, new Group(popupPane));
为何如此有效
Group 不可调整大小,因此效果是 mainPane 可调整大小,popupPane 将采用其内部首选大小并放置在一个 Group 中,该 Group 将由 StackPane 置于 mainPane 顶部的中心。
示范
DialogFactory在我很久以前写的一个项目中演示了这种在 WebView 之上覆盖对话框的方法。下面的屏幕截图显示了运行 willow-0.3-prerelease-jar 的输出在 Java 8 下并导航到 http://www.w3schools.com/js/tryit.asp?filename=tryjs_alert ,然后单击“试用”按钮。它所做的是将警告框(用 JavaFX 呈现和编程,而不是 JavaScript)覆盖在 WebView 控件的顶部,该控件在显示警告时被禁用和变暗。
示例源
这是从 willow project 中选择的来源,它不是独立的,但您需要稍微调整它以适应您的情况。此处仅提供代码以演示技术和模式。
/**
* Overlay a dialog on top of the WebView.
*
* @param dialogNode the dialog to overlay on top of the view.
*/
private void overlayView(Node dialogNode) {
// if the view is already overlaid we will just ignore this overlay call silently . . . todo probably not the best thing to do, but ok for now.
if (!(webView.getParent() instanceof BorderPane)) return;
// record the view's parent.
BorderPane viewParent = (BorderPane) webView.getParent();
// create an overlayPane layering the popup on top of the webview
StackPane overlayPane = new StackPane();
overlayPane.getChildren().addAll(webView, new Group(dialogNode));
webView.setDisable(true);
// overlay the popup on the webview.
viewParent.setCenter(overlayPane);
}
/**
* Removes an existing dialog overlaying a WebView.
*/
private void removeViewOverlay() {
BorderPane viewParent = (BorderPane) webView.getParent().getParent();
viewParent.setCenter(webView);
}
public EventHandler<WebEvent<String>> createAlertHandler() {
return stringWebEvent -> {
AlertHandler alertHandler = new AlertHandler(
stringWebEvent.getData(),
event -> {
webView.setDisable(false);
removeViewOverlay();
}
);
overlayView(alertHandler);
// todo block until the user accepts the alert.
};
}
. . .
// add an effect for disabling and enabling the view.
getView().disabledProperty().addListener(new ChangeListener<Boolean>() {
final BoxBlur soften = new BoxBlur();
final ColorAdjust dim = new ColorAdjust();
{
dim.setInput(soften);
dim.setBrightness(-0.5);
}
@Override
public void changed(ObservableValue<? extends Boolean> observableValue, Boolean oldValue, Boolean newValue) {
if (newValue) {
getView().setEffect(dim);
} else {
getView().setEffect(null);
}
}
});
. . .
public class AlertHandler extends VBox {
public AlertHandler(String message, EventHandler<ActionEvent> confirmHandler) {
super(14);
// add controls to the popup.
final Label promptMessage = new Label(message);
final ImageView alertImage = new ImageView(ResourceUtil.getImage("alert_48.png"));
alertImage.setFitHeight(32);
alertImage.setPreserveRatio(true);
promptMessage.setGraphic(alertImage);
promptMessage.setWrapText(true);
promptMessage.setPrefWidth(350);
// action button text setup.
HBox buttonBar = new HBox(20);
final Button confirmButton = new Button(getString("dialog.continue"));
confirmButton.setDefaultButton(true);
buttonBar.getChildren().addAll(confirmButton);
// layout the popup.
setPadding(new Insets(10));
getStyleClass().add("alert-dialog");
getChildren().addAll(promptMessage, buttonBar);
final DropShadow dropShadow = new DropShadow();
setEffect(dropShadow);
// confirm and close the popup.
confirmButton.setOnAction(confirmHandler);
}
}
. . .
getView().getEngine().setOnAlert(dialogFactory.createAlertHandler());
真的,我写上面代码的唯一原因是因为当时没有可用的 ControlsFX 等效库。如果我从头开始开发项目,我会首先尝试使用 ControlsFX。
关于java - StackPane 中的居中弹出 Pane ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22184172/