使用弹出窗口扩展JavaFX阶段内容(?)
这是我在这里的第一篇帖子——请友好一点:) 我想做的是让控件/窗口:使用弹出窗口扩展JavaFX阶段内容(?),javafx,popup,stage,always-on-top,Javafx,Popup,Stage,Always On Top,这是我在这里的第一篇帖子——请友好一点:) 我想做的是让控件/窗口: 属于JavaFX阶段 单击时不会从所属阶段窃取焦点 可以拖动到所属阶段的边界之外 我通过两种方式实现了这一点;然而,两者都有缺陷。首先,我在舞台内容中制作了可拖动的控件;但是,它们不能拖到舞台区域之外。其次,我将它们创建为固定在舞台上的可拖动弹出窗口;然而,即使其他窗口被移动到所属阶段的顶部,它们仍然位于所有内容的顶部 我要问的是:是否有任何方法可以将控件拖出其所属阶段的边界;或者使弹出窗口不总是显示在所有内容的顶部? 我在这
我通过两种方式实现了这一点;然而,两者都有缺陷。首先,我在舞台内容中制作了可拖动的控件;但是,它们不能拖到舞台区域之外。其次,我将它们创建为固定在舞台上的可拖动弹出窗口;然而,即使其他窗口被移动到所属阶段的顶部,它们仍然位于所有内容的顶部 我要问的是:是否有任何方法可以将控件拖出其所属阶段的边界;或者使弹出窗口不总是显示在所有内容的顶部? 我在这里发现了一个类似的问题,解释了弹出窗口位于顶部()的问题。但是没有可接受的解决方案(我不希望在舞台或应用程序失去焦点时弹出窗口“隐藏”) 谢谢你的阅读。如果您能提出任何建议,我们将不胜感激 下面是我用MoveablePopup尝试的MCV示例。它可以正常工作,除了在顶部加上额外的窗口
package moveablepopuptest;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Popup;
import javafx.stage.Stage;
public class MoveablePopupTest extends Application
{
@Override
public void start(Stage primaryStage)
{
// Set up Primary Stage:
StackPane root = new StackPane();
Scene scene = new Scene(root, 400, 400);
primaryStage.setTitle("MoveablePopup Test");
primaryStage.setScene(scene);
primaryStage.show();
// Show a MoveablePopup for an associated node in the Stage:
MoveablePopup popup = new MoveablePopup();
popup.setTitle("Extension");
Pane popupContent = new Pane();
popupContent.setBackground(new Background(new BackgroundFill(Color.WHITE, CornerRadii.EMPTY, Insets.EMPTY)));
popupContent.setMinSize(200, 200);
popup.setContent(popupContent);
popup.show(root, 0, 0);
// When Primary Stage is moved, re-anchor the popup:
ChangeListener<Number> windowMoveListener = (ObservableValue<? extends Number> observable, Number oldValue, Number newValue) ->
{
popup.anchorToOwner();
};
primaryStage.xProperty().addListener(windowMoveListener);
primaryStage.yProperty().addListener(windowMoveListener);
}
public static void main(String[] args)
{
launch(args);
}
public class MoveablePopup extends Popup
{
private final BorderPane bgPane = new BorderPane();
private final DoubleProperty ownerXAnchorProperty = new SimpleDoubleProperty(0);
private final DoubleProperty ownerYAnchorProperty = new SimpleDoubleProperty(0);
private final Label titleLabel = new Label("Title");
private Point2D lastMouse = null;
private Node content = null;
public MoveablePopup()
{
// Don't want Esc to close the Popup:
setHideOnEscape(false);
// Create a border:
bgPane.setBorder(new Border(new BorderStroke(Color.DARKORANGE, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, new BorderWidths(2))));
// Create a title bar for the top, which will also function as a handle to move the Popup:
StackPane barPane = new StackPane();
titleLabel.setTextFill(Color.WHITE);
barPane.getChildren().add(titleLabel);
barPane.setCursor(Cursor.MOVE);
barPane.setBackground(new Background(new BackgroundFill(Color.DARKORANGE, CornerRadii.EMPTY, Insets.EMPTY)));
barPane.setMaxSize(Double.MAX_VALUE, 24);
bgPane.setTop(barPane);
// Add drag/anchoring functionality to the Popup
barPane.setOnMousePressed((MouseEvent event) ->
{
lastMouse = new Point2D(event.getScreenX(), event.getScreenY());
});
barPane.setOnMouseDragged((MouseEvent event) ->
{
double moveX = event.getScreenX() - lastMouse.getX();
double moveY = event.getScreenY() - lastMouse.getY();
ownerXAnchorProperty.set(ownerXAnchorProperty.doubleValue()+moveX);
ownerYAnchorProperty.set(ownerYAnchorProperty.doubleValue()+moveY);
lastMouse = new Point2D(event.getScreenX(), event.getScreenY());
anchorToOwner();
});
getContent().add(bgPane);
}
@Override
protected void show()
{
super.show();
anchorToOwner();
}
public void setContent(Node content)
{
this.content = content;
bgPane.setCenter(content);
}
public void setTitle(String title)
{
titleLabel.setText(title);
}
// Repositions the MoveablePopup so that it's relationship to
// the owning Node's location is maintained:
public final void anchorToOwner()
{
if (getOwnerNode() != null)
{
Point2D screenPoint = getOwnerNode().localToScreen(0, 0);
setX(screenPoint.getX() + ownerXAnchorProperty.doubleValue());
setY(screenPoint.getY() + ownerYAnchorProperty.doubleValue());
}
}
}
}
packagemoveablepoputest;
导入javafx.application.application;
导入javafx.beans.property.DoubleProperty;
导入javafx.beans.property.SimpleDoubleProperty;
导入javafx.beans.value.ChangeListener;
导入javafx.beans.value.observeValue;
导入javafx.geometry.Insets;
导入javafx.geometry.Point2D;
导入javafx.scene.Cursor;
导入javafx.scene.Node;
导入javafx.scene.scene;
导入javafx.scene.control.Label;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.layout.Background;
导入javafx.scene.layout.BackgroundFill;
导入javafx.scene.layout.Border;
导入javafx.scene.layout.BorderPane;
导入javafx.scene.layout.BorderStroke;
导入javafx.scene.layout.BorderStrokeStyle;
导入javafx.scene.layout.BorderWidths;
导入javafx.scene.layout.CornerRadii;
导入javafx.scene.layout.Pane;
导入javafx.scene.layout.StackPane;
导入javafx.scene.paint.Color;
导入javafx.stage.Popup;
导入javafx.stage.stage;
公共类MoveablePopupTest扩展了应用程序
{
@凌驾
公共无效开始(阶段primaryStage)
{
//建立初级阶段:
StackPane root=新的StackPane();
场景=新场景(根,400400);
primaryStage.setTitle(“可移动弹出测试”);
初级阶段。场景(场景);
primaryStage.show();
//显示阶段中关联节点的可移动弹出窗口:
MoveablePopup popup=新的MoveablePopup();
popup.setTitle(“扩展”);
窗格popupContent=新窗格();
popupContent.setBackground(新背景(新背景填充(Color.WHITE,CornerRadii.EMPTY,Insets.EMPTY));
setMinSize(200200);
popup.setContent(popupContent);
显示(根,0,0);
//移动主阶段时,重新锚定弹出窗口:
ChangeListener windowMoveListener=(ObservalEvalue正如您所发现的,舞台内发生的一切都留在舞台内(请原谅双关语)。因此,如果您需要在后台之外显示某些内容,我们可以排除除后台
本身以外的所有内容。您可以创建一个新后台,并将所有者分配给初始后台。后台
,作为本机窗口的一种表示形式,将窃取对单击的关注。但是,可以在初始后台返回。这应该勾选您的需求框
我不确定您试图实现的用例,但提供了对现有JavaFX API的一些扩展,包括通知和窗口。看看这对您是否有帮助。正如您所发现的,阶段内发生的一切都在阶段内(请原谅双关语)。因此,如果您需要在后台之外显示某些内容,我们可以排除除后台
本身以外的所有内容。您可以创建一个新后台,并将所有者分配给初始后台。后台
,作为本机窗口的一种表示形式,将窃取对单击的关注。但是,可以在初始后台返回。这应该勾选您的需求框
我不确定您尝试实现的用例,但提供了对现有JavaFX API的一些扩展,包括通知和窗口。看看这对您是否有帮助。创建一个新的阶段,它将是“弹出窗口”:
Stage childStage = new Stage();
childStage.initModality(Modality.WINDOW_MODAL);
childStage.setTitle("Title of popup");
childStage.setScene(YOUR_SCENE);
childStage.sizeToScene();
childStage.setResizable(false);
childStage.show();
创建一个新阶段,该阶段将成为“弹出窗口”:
Stage childStage = new Stage();
childStage.initModality(Modality.WINDOW_MODAL);
childStage.setTitle("Title of popup");
childStage.setScene(YOUR_SCENE);
childStage.sizeToScene();
childStage.setResizable(false);
childStage.show();
我知道这似乎没有什么帮助,但请在你的问题中加入一个你已经尝试过的方法。好吧,我添加了一个MoveablePopup方法的示例。至于在舞台上拖动控件:我认为这更简单,不能将它们从舞台上拖下来的问题更清楚;但是我如果您愿意,也可以添加一个示例。不,弹出窗口示例足以帮助演示问题。如果不创建子类窗口(如弹出窗口),则无法实现您的愿望,所以你不能用一个阶段作为你应用程序中的唯一窗口。这就是我害怕的。除了那个烦人的细节,我似乎离你很近……哈。好吧,谢谢你提供的信息。“我将它们创建为锚定在舞台上的可拖动弹出窗口;但是,即使其他窗口移动到舞台的顶部,它们仍然位于所有窗口的顶部。"-->我在OS X 10.9.5、Java 8u72上运行了您的示例,但没有得到此行为。当我将其他窗口移动到所属阶段的顶部时,其他窗口也会阻塞弹出窗口。我知道这似乎没有帮助,但请在您的问题中包含一个示例,说明您已经尝试过的内容。好的,我为MoveablePopup添加了一个示例接近