使用Popup(?)扩展JavaFXStage内容



这是我在这里的第一篇文章-请注意:)

我想做的是让控件/窗口:

  1. 属于JavaFX阶段
  2. 点击时不会从拥有的舞台上窃取焦点
  3. 可以拖动到所属阶段的边界之外

我已经能够通过两种方式实现这一点;然而,两者都有缺陷。首先,我在舞台的内容中进行了可拖动的控制;但是,它们不能被拖到舞台的区域之外。第二,我把它们创建为可拖动的弹出菜单,固定在舞台上;然而,即使其他窗口被移动到所属阶段的顶部,它们仍然位于所有之上。

我想问的是:有没有任何方法可以将控件拖到它拥有的Stage的边界之外;或者让弹出菜单不总是出现在所有内容的顶部

我在这里发现了一个类似的问题,解释了Popup在顶部的问题(Javafx 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());
            }
        }
    }   
}

创建一个新阶段,该阶段将成为"弹出窗口":

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本身之外的所有内容。您可以创建一个新阶段,并将您的初始阶段分配给所有者。Stage作为本机窗口的表示,将在单击时抢占焦点。但是,可以在初始阶段请求重新聚焦。这应该勾选你的要求框。

我不确定您试图实现的用例,但JFXtra为现有的JavaFX API提供了一些扩展,包括通知和MDI窗口。看看这对你有没有帮助。

相关内容

  • 没有找到相关文章

最新更新