淡入淡出的 JavaFX 弹出窗口允许额外的内容

发布于 2025-01-08 19:54:29 字数 6866 浏览 2 评论 0原文

这是一个要添加为弹出窗口的类,类似于 JQuery 模式对话框...并且通过绑定,您可以添加内容并且它将重新调整大小,我没有成功地缩小大小,因为内容大小保持不变,直到弹出窗口已关闭.. 请随意评论、改进、定制和使用

在此处输入图像描述

它固定在 的中心屏幕上,但是有一点可以移动的编码..(我只是还没有打扰)

问候D07114915

  package Utilities;

import javafx.animation.FadeTransition;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBuilder;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.RectangleBuilder;
import javafx.util.Duration;

public class PopupMenu {

    private Group group;
    private Scene scene;
    private Node content;
    private Pane pane;
    private StackPane stackpane;
    private TilePane tile;
    private Rectangle outRectangle, inRectangle, borderRectangle;
    private Button closeBtn;
    private final Double MIN_HEIGHT = 60.0, MIN_WIDTH = 80.0;
    private Double height, width;
    private final SimpleDoubleProperty sdpHeightInRect = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty sdpWidthInRect = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty sdpHeightBorderRect = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty sdpWidthBorderRect = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty tileX = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty tileY = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty closeBtnX = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty closeBtnY = new SimpleDoubleProperty(0);
    private final int BORDER_SIZE = 3;
    private final int CONTENT_PADDING = 20;

    public PopupMenu(final Scene scene, final Node content) {
        this.content = content;
        this.content.setVisible(true);
        this.content.layoutBoundsProperty().addListener(new InvalidationListener() {

            @Override
            public void invalidated(Observable observable) {
                calculateWidthAndHeight();
            }
        });

        this.group = (Group) scene.getRoot();
        this.scene = scene;

        outRectangle = RectangleBuilder.create().width(scene.getWidth() - 2).height(scene.getHeight() - 2).opacity(0.2).fill(Color.BLACK).onMouseReleased(new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent event) {
                event.consume();
                closeMenu();
            }
        }).build();

        inRectangle = RectangleBuilder.create().width(sdpHeightInRect.get()).height(sdpWidthInRect.get()).fill(Color.WHITESMOKE).arcHeight(10).arcWidth(10).opacity(0.9).build();
        inRectangle.heightProperty().bindBidirectional(sdpHeightInRect);
        inRectangle.widthProperty().bindBidirectional(sdpWidthInRect);

        borderRectangle = RectangleBuilder.create().width(sdpWidthBorderRect.get()).height(sdpHeightBorderRect.get()).arcHeight(10).arcWidth(10).opacity(0.9).build();
        borderRectangle.heightProperty().bindBidirectional(sdpHeightBorderRect);
        borderRectangle.widthProperty().bindBidirectional(sdpWidthBorderRect);

        tile = TilePaneBuilder.create().orientation(Orientation.HORIZONTAL).tileAlignment(Pos.CENTER).managed(false).children(this.content).build();
        tile.layoutXProperty().bindBidirectional(tileX);
        tile.layoutYProperty().bindBidirectional(tileY);

        stackpane = StackPaneBuilder.create().alignment(Pos.CENTER).children(outRectangle, borderRectangle, inRectangle, tile).build();

        closeBtn = ButtonBuilder.create().text("[X]").cancelButton(true).visible(true).onAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                closeMenu();
            }
        }).build();

        closeBtn.layoutXProperty().bindBidirectional(closeBtnX);
        closeBtn.layoutYProperty().bindBidirectional(closeBtnY);

        pane = PaneBuilder.create().children(stackpane, closeBtn).build();

        //This is needed to fire to set everything first time around. Otherwise the display is not centered
        // when the popup is shown on subsequent ocasions without the content being altered
                calculateWidthAndHeight();
    }

    public void openMenu() {
        group.getChildren().addAll(pane);

        FadeTransition fadein = new FadeTransition(Duration.millis(800), pane);
        fadein.setFromValue(0.0);
        fadein.setToValue(1.0);
        fadein.play();
    }

    public void closeMenu() {
        FadeTransition fadeout = new FadeTransition(Duration.millis(700), pane);
        fadeout.setFromValue(1.0);
        fadeout.setToValue(0.0);
        fadeout.play();
        fadeout.setOnFinished(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                group.getChildren().removeAll(pane);
            }
        });
    }

    private void calculateWidthAndHeight() {
        Bounds boundsInLocal = this.content.getBoundsInLocal();
        height = (boundsInLocal.getHeight() < MIN_HEIGHT) ? MIN_HEIGHT : boundsInLocal.getHeight();
        width = (boundsInLocal.getWidth() < MIN_WIDTH) ? MIN_WIDTH : boundsInLocal.getWidth();

        sdpHeightInRect.set(height + CONTENT_PADDING);
        sdpWidthInRect.set(width + CONTENT_PADDING);

        sdpHeightBorderRect.set(sdpHeightInRect.get() + BORDER_SIZE);
        sdpWidthBorderRect.set(sdpWidthInRect.get() + BORDER_SIZE);

        tileX.set(scene.getWidth() / 2 - width / 2);
        tileY.set(scene.getHeight() / 2 - height / 2);

        closeBtnX.set((scene.getWidth() / 2) - 18);
        closeBtnY.set((scene.getHeight() - (scene.getHeight() - borderRectangle.getHeight()) / 2) - (((borderRectangle.getHeight() - inRectangle.getHeight()) * 2)) - 5);
        System.err.println("H:" + height + ", W:" + width);
    }
}// end of class

要在你的主类中触发它,你会做这样的事情

Scene scene;

VBox popupBOX = VBoxBuilder.create().children(new Label("MY CONTENT").visible(false).build();

        final Button firePopup = ButtonBuilder.create().text("FIRE POPUP").build()).onAction(new EventHandler() {

        @Override
        public void handle(Event event) {
            new PopupMenu(scene, popupBOX).openMenu();
        }
    }).build()

并注意popupBOX节点应该已经添加到当前工作场景中(这允许计算布局、宽度等),它只是隐藏的,但在 PopupMenu 类中设置为可见......

Here's a class to add as a popup , similar to JQuery modal dialog... And with the bindings you can add content and it will re size up, I'm not succeeding in re sizing down as the content size remains the same until the popup is closed.. Feel free to comment , improve, tailor and use

enter image description here

It is fixed to the center of the screen, but with a little bit of coding that can be movable.. (i just haven't bothered yet)

Regards D07114915

  package Utilities;

import javafx.animation.FadeTransition;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBuilder;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.RectangleBuilder;
import javafx.util.Duration;

public class PopupMenu {

    private Group group;
    private Scene scene;
    private Node content;
    private Pane pane;
    private StackPane stackpane;
    private TilePane tile;
    private Rectangle outRectangle, inRectangle, borderRectangle;
    private Button closeBtn;
    private final Double MIN_HEIGHT = 60.0, MIN_WIDTH = 80.0;
    private Double height, width;
    private final SimpleDoubleProperty sdpHeightInRect = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty sdpWidthInRect = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty sdpHeightBorderRect = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty sdpWidthBorderRect = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty tileX = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty tileY = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty closeBtnX = new SimpleDoubleProperty(0);
    private final SimpleDoubleProperty closeBtnY = new SimpleDoubleProperty(0);
    private final int BORDER_SIZE = 3;
    private final int CONTENT_PADDING = 20;

    public PopupMenu(final Scene scene, final Node content) {
        this.content = content;
        this.content.setVisible(true);
        this.content.layoutBoundsProperty().addListener(new InvalidationListener() {

            @Override
            public void invalidated(Observable observable) {
                calculateWidthAndHeight();
            }
        });

        this.group = (Group) scene.getRoot();
        this.scene = scene;

        outRectangle = RectangleBuilder.create().width(scene.getWidth() - 2).height(scene.getHeight() - 2).opacity(0.2).fill(Color.BLACK).onMouseReleased(new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent event) {
                event.consume();
                closeMenu();
            }
        }).build();

        inRectangle = RectangleBuilder.create().width(sdpHeightInRect.get()).height(sdpWidthInRect.get()).fill(Color.WHITESMOKE).arcHeight(10).arcWidth(10).opacity(0.9).build();
        inRectangle.heightProperty().bindBidirectional(sdpHeightInRect);
        inRectangle.widthProperty().bindBidirectional(sdpWidthInRect);

        borderRectangle = RectangleBuilder.create().width(sdpWidthBorderRect.get()).height(sdpHeightBorderRect.get()).arcHeight(10).arcWidth(10).opacity(0.9).build();
        borderRectangle.heightProperty().bindBidirectional(sdpHeightBorderRect);
        borderRectangle.widthProperty().bindBidirectional(sdpWidthBorderRect);

        tile = TilePaneBuilder.create().orientation(Orientation.HORIZONTAL).tileAlignment(Pos.CENTER).managed(false).children(this.content).build();
        tile.layoutXProperty().bindBidirectional(tileX);
        tile.layoutYProperty().bindBidirectional(tileY);

        stackpane = StackPaneBuilder.create().alignment(Pos.CENTER).children(outRectangle, borderRectangle, inRectangle, tile).build();

        closeBtn = ButtonBuilder.create().text("[X]").cancelButton(true).visible(true).onAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                closeMenu();
            }
        }).build();

        closeBtn.layoutXProperty().bindBidirectional(closeBtnX);
        closeBtn.layoutYProperty().bindBidirectional(closeBtnY);

        pane = PaneBuilder.create().children(stackpane, closeBtn).build();

        //This is needed to fire to set everything first time around. Otherwise the display is not centered
        // when the popup is shown on subsequent ocasions without the content being altered
                calculateWidthAndHeight();
    }

    public void openMenu() {
        group.getChildren().addAll(pane);

        FadeTransition fadein = new FadeTransition(Duration.millis(800), pane);
        fadein.setFromValue(0.0);
        fadein.setToValue(1.0);
        fadein.play();
    }

    public void closeMenu() {
        FadeTransition fadeout = new FadeTransition(Duration.millis(700), pane);
        fadeout.setFromValue(1.0);
        fadeout.setToValue(0.0);
        fadeout.play();
        fadeout.setOnFinished(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                group.getChildren().removeAll(pane);
            }
        });
    }

    private void calculateWidthAndHeight() {
        Bounds boundsInLocal = this.content.getBoundsInLocal();
        height = (boundsInLocal.getHeight() < MIN_HEIGHT) ? MIN_HEIGHT : boundsInLocal.getHeight();
        width = (boundsInLocal.getWidth() < MIN_WIDTH) ? MIN_WIDTH : boundsInLocal.getWidth();

        sdpHeightInRect.set(height + CONTENT_PADDING);
        sdpWidthInRect.set(width + CONTENT_PADDING);

        sdpHeightBorderRect.set(sdpHeightInRect.get() + BORDER_SIZE);
        sdpWidthBorderRect.set(sdpWidthInRect.get() + BORDER_SIZE);

        tileX.set(scene.getWidth() / 2 - width / 2);
        tileY.set(scene.getHeight() / 2 - height / 2);

        closeBtnX.set((scene.getWidth() / 2) - 18);
        closeBtnY.set((scene.getHeight() - (scene.getHeight() - borderRectangle.getHeight()) / 2) - (((borderRectangle.getHeight() - inRectangle.getHeight()) * 2)) - 5);
        System.err.println("H:" + height + ", W:" + width);
    }
}// end of class

To fire this in your main class you would do something like this

Scene scene;

VBox popupBOX = VBoxBuilder.create().children(new Label("MY CONTENT").visible(false).build();

        final Button firePopup = ButtonBuilder.create().text("FIRE POPUP").build()).onAction(new EventHandler() {

        @Override
        public void handle(Event event) {
            new PopupMenu(scene, popupBOX).openMenu();
        }
    }).build()

And note the popupBOX node should be added already to the current working scene(This allows the calculation of layout, width etc), it is just hidden, but is set visible in the PopupMenu class....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文