淡入淡出的 JavaFX 弹出窗口允许额外的内容
这是一个要添加为弹出窗口的类,类似于 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
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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论