这是我在这里的第一篇文章 - 请保持友好:)
我要做的是控制/窗口:
我已经能够以两种方式实现这一点;然而,两者都有缺陷。首先,我在舞台的内容中制作了可拖动的控件;但是,他们不能被拖到舞台区域之外。其次,我创建了它们作为可拖动的Popups锚定到舞台;但是,即使其他窗口移动到拥有舞台之上,它们仍然在一切之上。
我要问的是:有没有办法将控件拖出它拥有舞台的范围之外;或者让Popup并不总是出现在所有内容之上?
我在这里找到了一个类似的问题,解释了Popup在顶部的问题(Javafx popup won't hide behind other application upon losing focus)。但那里没有可接受的解决方案(当舞台或应用程序失去焦点时,我不希望Popup“隐藏”。)
感谢阅读。如果你能提出任何建议,我们将不胜感激。
下面是我尝试使用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());
}
}
}
}
答案 0 :(得分:0)
创建一个新的舞台,它将是'popup':
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();
答案 1 :(得分:-1)
正如你已经发现的那样,舞台上发生的一切都停留在舞台之内(请原谅双关语)。因此,如果您需要在舞台外显示某些内容,我们可以排除除Stage
之外的所有内容。您可以创建一个新阶段并为所有者分配初始阶段。 Stage
,作为原生窗口的代表,将专注于点击。但是,有可能here回到初始阶段。这应该勾选你的需求框。
我不确定您要尝试实现的用例,但request focus提供了对现有JavaFX API的一些扩展,包括通知和JFXtras窗口。看看这对你有什么帮助。