2013-07-16 4 views
5

Я нашел этот пример внутреннего FramesВнутренние Фреймы в JavaFX

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

Можно ли сделать те же внутренние кадры в JavaFX?

+0

Посмотрите на http://jfxtras.org/ у них есть внутреннее окно осуществление довольно хорошее. У них есть демоверсия, где вы можете их протестировать. –

+0

Я попытался открыть демонстрационное приложение, но не повезло. Кажется, что JVM 7_25 64 не может запускать эти примеры. –

+0

У меня возникает соблазн сказать «конечно не», что «не может работать ...», поскольку это касается JavaFX и, скорее всего, совместимо только с JavaFX 8 (т.е. частью Java 8, включая зависимость от lambdas и др.) –

ответ

10

С JFXtras есть окно управления, в котором вы можете добавлять контент и обрабатывать поведение внутреннего окна.

Сначала вам нужно будет поместить в свой класс путь библиотеки jfxtras. У них есть некоторые инструкции, где вы можете получить библиотеку. Если вы используете Maven, просто нужно добавить:

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

Или скачать библиотеку и поместить его в свой проект, независимо от пути к классам.

Теперь я поставил образец демонстрации окна с небольшой разницей, позволяя создавать несколько окон.

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

В исходной демонстрации код события был в методе init, и кнопка не была включена. Я добавляю кнопку для создания динамически окон и добавления их на экран.

Вот снимок результата применения:

snapshot

Я полностью рекомендую вам попробовать демо jfxtras. У них действительно отличные вещи. Надеюсь, поможет.

+0

Спасибо за ответ! Какую версию JVM вы используете? –

+0

Я использую jdk7u10. Но с более чем одной версией java, я не уверен, какая версия будет выполнена. Другой вариант - ждать, пока jfxtras не получит демоверсию, которая должным образом работает с последней версией java. –

9

Вы можете реализовать простое внутреннее окно самостоятельно. Основная идея, что InternalWindow класс просто скелет, который имеет встроенный фрейм, как функциональность. Вы можете применить к нему любой контент.

1) Объявить класс

public class InternalWindow extends Region 

2) Вы должны быть в состоянии установить содержание в окне

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

3) Вы должны быть в состоянии переместить окно на передний план, если многие окна существуют

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

4) Теперь нам нужно перетащить функциональность

//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) Кроме того, мы хотим, чтобы иметь возможность изменять размер окна (я показываю только простой правый нижний изменение размера)

//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) Использование. Сначала мы строим все макеты. Затем примените его к 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) И как добавить окно 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(); 
} 

Результат

enter image description here

Полный код: gist

Up d о кнопке закрытия:

Вы можете добавить метод InternalWindow

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

И когда конструкция:

interalWindow.setCloseButton(closeButton); 
+0

Я заметил, что кнопка X не имеет никаких действий, связанных с ней - как бы вы удалили внутреннее окно со сцены при нажатии кнопки? –

+1

@RishiPochiraju Я обновил ответ – zella

 Смежные вопросы

  • Нет связанных вопросов^_^