Znalazłem ten przykład Wewnętrznego FramesRamki wewnętrzne w JavaFX
http://docs.oracle.com/javase/tutorial/uiswing/components/internalframe.html
Czy to możliwe, aby te same ramek wewnętrznych w JavaFX?
Znalazłem ten przykład Wewnętrznego FramesRamki wewnętrzne w JavaFX
http://docs.oracle.com/javase/tutorial/uiswing/components/internalframe.html
Czy to możliwe, aby te same ramek wewnętrznych w JavaFX?
W opcji JFXtras znajduje się kontrolka okna, w której można dodawać zawartość i obsługiwać zachowanie okna wewnętrznego.
Najpierw musisz umieścić w swojej klasie bibliotekę jfxtras. Mają instrukcje, gdzie można dostać bibliotekę. Jeśli używasz maven, po prostu musisz dodać:
<dependency>
<groupId>org.jfxtras</groupId>
<artifactId>jfxtras-labs</artifactId>
<version>2.2-r5</version>
</dependency>
Lub pobierz bibliotekę i umieść ją w swojej ścieżce klas projektu, cokolwiek.
Teraz umieszczam próbkę demonstracji okna z niewielką różnicą, umożliwiając wygenerowanie kilku okien.
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);}
}
W oryginalnym demo kod zdarzenia był w metodzie init i nie został dołączony żaden przycisk. Dodaję przycisk, aby tworzyć dynamicznie okna i dodawać je do ekranu.
Oto zrzut wyniku zastosowania:
I całkowicie polecam wypróbować demo jfxtras. Mają naprawdę świetne rzeczy. Mam nadzieję, że to pomoże.
Dziękuję za odpowiedź! Z której wersji JVM korzystasz? –
Używam jdk7u10. Ale w przypadku zainstalowania więcej niż jednej wersji java, nie jestem pewien, która wersja zostanie wykonana. Inną opcją jest czekanie, aż jfxtras otrzyma wersję demonstracyjną, która działa poprawnie z najnowszą wersją java. –
Możesz samodzielnie zaimplementować proste okno wewnętrzne. Główny pomysł, że klasa InternalWindow
po prostu szkielet, który ma funkcjonalność wewnętrznej ramki. Możesz zastosować do niego dowolną treść.
1) stwierdzenie klasa
public class InternalWindow extends Region
2) powinien być w stanie ustawić zawartość w oknie
public void setRoot(Node node) {
getChildren().add(node);
}
3) powinien być w stanie przynieść okno do przodu, jeśli wielu okno istnieć
public void makeFocusable() {
this.setOnMouseClicked(mouseEvent -> {
toFront();
});
}
4) Teraz potrzebujemy funkcji przeciągania
//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) Również chcemy stanie rozmiar okna (pokażę tylko prosty prawy dolny zmiana rozmiaru)
//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) Wykorzystanie. Najpierw konstruujemy cały układ. Następnie zastosuj go do 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) A jak dodać do okna 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();
}
Wynik
pełny kod: gist
Up d o ścisłej przycisku:
Możesz dodać metodę InternalWindow
public void setCloseButton(Button btn) {
btn.setOnAction(event -> ((Pane) getParent()).getChildren().remove(this));
}
i kiedy konstrukt:
interalWindow.setCloseButton(closeButton);
Zauważyłem, że przycisk X nie ma żadnej akcji z nim związanej - w jaki sposób można by usunąć wewnętrzne okno ze sceny po naciśnięciu przycisku? –
@RishiPochiraju Zaktualizowałem odpowiedź – zella
Spójrz na http://jfxtras.org/ mają wewnętrzny okno wdrożenie dość dobre. Mają demo, w którym możesz je przetestować. –
Próbowałem otworzyć aplikację demo, ale bez powodzenia. Wydaje się, że JVM 7_25 64 nie może uruchomić tych przykładów. –
Mam ochotę powiedzieć "oczywiście, że nie" do "nie można uruchomić ...", ponieważ dotyczy to JavaFX i najprawdopodobniej jest kompatybilny tylko z JavaFX 8 (tj. Częścią Java 8, w tym poleganiem na lambdas et al.) –