2013-07-16 10 views
5

Ho trovato questo esempio di infissi interniinfissi interni in JavaFX

http://docs.oracle.com/javase/tutorial/uiswing/components/internalframe.html

E 'possibile fare gli stessi infissi interni in JavaFX?

+0

Date un'occhiata su http://jfxtras.org/ hanno una finestra interna implementazione abbastanza buona. Hanno una demo dove puoi provarli. –

+0

Ho provato ad aprire l'applicazione demo ma senza fortuna. Sembra che JVM 7_25 64 non possa eseguire questi esempi. –

+0

Sono tentato di dire "ovviamente no" al "non posso eseguire ..." visto che si tratta di JavaFX, e molto probabilmente compatibile solo con JavaFX 8 (cioè parte di Java 8, incluso affidamento su lambdas et al.) –

risposta

10

Con JFXtras c'è un controllo Finestra, in cui è possibile aggiungere contenuto e gestire il comportamento della finestra interna.

Per prima cosa è necessario inserire nel classpath la libreria jfxtras. Hanno alcune istruzioni dove puoi ottenere la biblioteca. Se si utilizza Maven, solo bisogno di aggiungere:

<dependency> 
    <groupId>org.jfxtras</groupId> 
    <artifactId>jfxtras-labs</artifactId> 
    <version>2.2-r5</version> 
</dependency> 

oppure scaricare la libreria e metterlo nel classpath del progetto, a prescindere.

Ora ho messo un esempio della demo della finestra con una piccola differenza, consentendo la generazione di diverse finestre.

import javafx.application.Application; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.stage.Stage; 
import jfxtras.labs.scene.control.window.CloseIcon; 
import jfxtras.labs.scene.control.window.MinimizeIcon; 
    import jfxtras.labs.scene.control.window.Window; 


public class WindowTests extends Application { 
private static int counter = 1; 

private void init(Stage primaryStage) { 
    final Group root = new Group(); 

    Button button = new Button("Add more windows");  

    root.getChildren().addAll(button); 
    primaryStage.setResizable(false); 
    primaryStage.setScene(new Scene(root, 600, 500)); 

    button.setOnAction(new EventHandler<ActionEvent>() {    
     @Override 
     public void handle(ActionEvent arg0) { 
      // create a window with title "My Window" 
      Window w = new Window("My Window#"+counter); 
      // set the window position to 10,10 (coordinates inside canvas) 
      w.setLayoutX(10); 
      w.setLayoutY(10); 
      // define the initial window size 
      w.setPrefSize(300, 200); 
      // either to the left 
      w.getLeftIcons().add(new CloseIcon(w)); 
      // .. or to the right 
      w.getRightIcons().add(new MinimizeIcon(w)); 
      // add some content 
      w.getContentPane().getChildren().add(new Label("Content... \nof the window#"+counter++)); 
      // add the window to the canvas 
      root.getChildren().add(w); 
     } 
    }); 
} 

public double getSampleWidth() {return 600;} 
public double getSampleHeight() {return 500;} 

@Override 
public void start(Stage primaryStage) throws Exception { 
    init(primaryStage); 
    primaryStage.show(); 


} 
    public static void main(String[] args) {launch(args);} 
} 

Nella demo originale, il codice evento era nel metodo init, e nessun pulsante è stato incluso. Aggiungo il pulsante per creare dinamicamente le finestre e aggiungerle allo schermo.

Ecco un'istantanea del risultato dell'applicazione:

snapshot

Consiglio vivamente di provare la demo di jfxtras. Hanno cose davvero grandiose. Spero che sia d'aiuto.

+0

Grazie per la risposta! Quale versione di JVM usi? –

+0

Sto usando jdk7u10. Ma con più di una versione di java installata, non sono abbastanza sicuro di quale versione verrà eseguita. L'altra opzione è aspettare che jfxtras abbia una demo che funzioni correttamente con l'ultima versione di java. –

9

È possibile implementare semplici finestre interne. Idea principale, quella classe InternalWindow solo scheletro, che ha funzionalità di frame interno. Puoi applicare qualsiasi contenuto ad esso.

1) dichiarare classe

public class InternalWindow extends Region 

2) Si dovrebbe essere in grado di impostare il contenuto in una finestra

public void setRoot(Node node) { 
     getChildren().add(node); 
} 

3) Si dovrebbe essere in grado di portare la finestra in primo piano se molti finestra esiste

public void makeFocusable() {  
     this.setOnMouseClicked(mouseEvent -> { 
      toFront(); 
     });  
} 

4) Ora è necessario trascinare la funzionalità

//just for encapsulation 
private static class Delta { 
    double x, y; 
} 

//we can select nodes that react drag event 
public void makeDragable(Node what) { 
    final Delta dragDelta = new Delta(); 
    what.setOnMousePressed(mouseEvent -> { 
     dragDelta.x = getLayoutX() - mouseEvent.getScreenX(); 
     dragDelta.y = getLayoutY() - mouseEvent.getScreenY(); 
     //also bring to front when moving 
     toFront(); 
    }); 
    what.setOnMouseDragged(mouseEvent -> { 
     setLayoutX(mouseEvent.getScreenX() + dragDelta.x); 
     setLayoutY(mouseEvent.getScreenY() + dragDelta.y); 
    }); 
} 

5) Inoltre vogliamo in grado di ridimensionare la finestra (mi mostra solo semplice ridimensionamento in basso a destra)

//current state 
private boolean RESIZE_BOTTOM; 
private boolean RESIZE_RIGHT; 

public void makeResizable(double mouseBorderWidth) { 
    this.setOnMouseMoved(mouseEvent -> { 
     //local window's coordiantes 
     double mouseX = mouseEvent.getX(); 
     double mouseY = mouseEvent.getY(); 
     //window size 
     double width = this.boundsInLocalProperty().get().getWidth(); 
     double height = this.boundsInLocalProperty().get().getHeight(); 
     //if we on the edge, change state and cursor 
     if (Math.abs(mouseX - width) < mouseBorderWidth 
       && Math.abs(mouseY - height) < mouseBorderWidth) { 
      RESIZE_RIGHT = true; 
      RESIZE_BOTTOM = true; 
      this.setCursor(Cursor.NW_RESIZE); 
     } else { 
      RESIZE_BOTTOM = false; 
      RESIZE_RIGHT = false; 
      this.setCursor(Cursor.DEFAULT); 
     } 

    }); 
    this.setOnMouseDragged(mouseEvent -> { 
     //resize root 
     Region region = (Region) getChildren().get(0); 
     //resize logic depends on state 
     if (RESIZE_BOTTOM && RESIZE_RIGHT) { 
      region.setPrefSize(mouseEvent.getX(), mouseEvent.getY()); 
     } else if (RESIZE_RIGHT) { 
      region.setPrefWidth(mouseEvent.getX()); 
     } else if (RESIZE_BOTTOM) { 
      region.setPrefHeight(mouseEvent.getY()); 
     } 
    }); 
} 

6) Uso. Per prima cosa costruiamo tutto il layout. Quindi applicalo a InternalWindow.

private InternalWindow constructWindow() { 
    // content 
    ImageView imageView = new ImageView("https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/Cheetah4.jpg/250px-Cheetah4.jpg"); 
    // title bar 
    BorderPane titleBar = new BorderPane(); 
    titleBar.setStyle("-fx-background-color: green; -fx-padding: 3"); 
    Label label = new Label("header"); 
    titleBar.setLeft(label); 
    Button closeButton = new Button("x"); 
    titleBar.setRight(closeButton); 
    // title bat + content 
    BorderPane windowPane = new BorderPane(); 
    windowPane.setStyle("-fx-border-width: 1; -fx-border-color: black"); 
    windowPane.setTop(titleBar); 
    windowPane.setCenter(imageView); 

    //apply layout to InternalWindow 
    InternalWindow interalWindow = new InternalWindow(); 
    interalWindow.setRoot(windowPane); 
    //drag only by title 
    interalWindow.makeDragable(titleBar); 
    interalWindow.makeDragable(label); 
    interalWindow.makeResizable(20); 
    interalWindow.makeFocusable(); 
    return interalWindow; 
} 

7) E come la finestra di layout

@Override 
public void start(Stage primaryStage) throws Exception { 
    Pane root = new Pane(); 
    root.getChildren().add(constructWindow()); 
    root.getChildren().add(constructWindow()); 
    primaryStage.setScene(new Scene(root, 300, 275)); 
    primaryStage.show(); 
} 

Risultato

enter image description here

codice completo aggiungere: gist

Up d in merito a pulsante di chiusura:

È possibile aggiungere metodo per InternalWindow

public void setCloseButton(Button btn) { 
    btn.setOnAction(event -> ((Pane) getParent()).getChildren().remove(this)); 
} 

E quando costrutto:

interalWindow.setCloseButton(closeButton); 
+0

Ho notato che il pulsante X non ha alcuna azione associata: come rimuovere la finestra interna dallo stage quando si preme il pulsante? –

+1

@RishiPochiraju Ho aggiornato la risposta – zella