Estensione del contenuto dello stage JavaFX con Popup (?)


È il mio primo post qui-per favore sii gentile:)

Quello che sto cercando di fare è avere controlli / finestre che:

  1. appartengono a uno stadio JavaFX
  2. NON ruberà l'attenzione dalla fase di possesso quando si fa clic su
  3. può essere trascinato oltre i confini dello Stadio proprietario

Sono stato in grado di implementarlo in due modi; tuttavia, entrambi sono difettosi. Innanzitutto, ho creato controlli trascinabili all'interno del contenuto dello Stage; tuttavia, non possono essere trascinati all'esterno dello Stage area. In secondo luogo, li ho creati come popup trascinabili ancorati allo Stage; tuttavia, rimangono in cima a TUTTO, anche quando altre finestre vengono spostate in cima allo Stadio proprietario.

Quello che sto chiedendo è: C'è un modo per trascinare un controllo al di fuori dei limiti del suo stadio proprietario; o per far apparire un Popup NON sempre in cima a tutto?

Ho trovato una domanda simile qui, spiegando il problema con il Popup in cima ( Il popup Javafx non lo farà nasconditi dietro un'altra applicazione dopo aver perso la messa a fuoco). Ma non c'era una soluzione accettabile lì (non voglio che il Popup" si nasconda " quando lo Stage o l'Applicazione perde il focus).

Grazie per la lettura. Se potessi suggerire qualcosa, sarebbe apprezzato.

Di seguito è riportato un esempio MCV di quello che ho provato con MoveablePopup. Funziona bene, tranne quando si mettono finestre aggiuntive sopra le righe.

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());
            }
        }

    }   
}
Author: Community, 2016-01-11

2 answers

Crea una nuova fase che sarà il'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();
 0
Author: Siloft, 2016-01-11 20:20:33

Come hai scoperto, tutto ciò che accade all'interno dello stage, rimane all'interno dello stage (scusa il gioco di parole). Quindi, se hai bisogno di alcuni contenuti mostrati al di fuori dello stage, possiamo escludere tutto tranne Stage stesso. È possibile creare una nuova fase e assegnare proprietario la fase iniziale. Stage, essendo una rappresentazione di una finestra nativa, ruberà il focus sul clic. Tuttavia, è possibile richiedere il focus indietro dalla fase iniziale. Questo dovrebbe spuntare le caselle dei requisiti.

Non lo sono sicuro del caso d'uso di ciò che si sta tentando di implementare, ma JFXtras fornisce alcune estensioni all'API JavaFX esistente, incluse le notifiche e MDI windows. Vedere se questo è di qualche aiuto per voi.

 -1
Author: AlmasB, 2016-01-11 19:11:04