Я нашел этот пример внутреннего FramesВнутренние Фреймы в JavaFX
http://docs.oracle.com/javase/tutorial/uiswing/components/internalframe.html
Можно ли сделать те же внутренние кадры в JavaFX?
Я нашел этот пример внутреннего FramesВнутренние Фреймы в JavaFX
http://docs.oracle.com/javase/tutorial/uiswing/components/internalframe.html
Можно ли сделать те же внутренние кадры в JavaFX?
С 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, и кнопка не была включена. Я добавляю кнопку для создания динамически окон и добавления их на экран.
Вот снимок результата применения:
Я полностью рекомендую вам попробовать демо jfxtras. У них действительно отличные вещи. Надеюсь, поможет.
Спасибо за ответ! Какую версию JVM вы используете? –
Я использую jdk7u10. Но с более чем одной версией java, я не уверен, какая версия будет выполнена. Другой вариант - ждать, пока jfxtras не получит демоверсию, которая должным образом работает с последней версией java. –
Вы можете реализовать простое внутреннее окно самостоятельно. Основная идея, что 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();
}
Результат
Полный код: gist
Up d о кнопке закрытия:
Вы можете добавить метод InternalWindow
public void setCloseButton(Button btn) {
btn.setOnAction(event -> ((Pane) getParent()).getChildren().remove(this));
}
И когда конструкция:
interalWindow.setCloseButton(closeButton);
Я заметил, что кнопка X не имеет никаких действий, связанных с ней - как бы вы удалили внутреннее окно со сцены при нажатии кнопки? –
@RishiPochiraju Я обновил ответ – zella
Посмотрите на http://jfxtras.org/ у них есть внутреннее окно осуществление довольно хорошее. У них есть демоверсия, где вы можете их протестировать. –
Я попытался открыть демонстрационное приложение, но не повезло. Кажется, что JVM 7_25 64 не может запускать эти примеры. –
У меня возникает соблазн сказать «конечно не», что «не может работать ...», поскольку это касается JavaFX и, скорее всего, совместимо только с JavaFX 8 (т.е. частью Java 8, включая зависимость от lambdas и др.) –