在JavaFX的内部框架在JavaFX的内部框架(Internal Frames in JavaFX

2019-05-12 03:33发布

我发现内部框架的这个例子

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

是否有可能使JavaFX中相同的内部框架?

Answer 1:

随着JFXtras有一个窗口的控制,在这里你可以添加内容和处理内部窗口行为。

首先,你需要把你的classpath中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的演示。 他们有真正伟大的东西。 希望能帮助到你。



Answer 2:

您可以实现简单的内部窗口本身。 主要想法,那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),以及如何添加窗口布局

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

结果

全码: 要点

UPD关于关闭按钮:

您可以添加方法InternalWindow

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

当结构:

interalWindow.setCloseButton(closeButton);


文章来源: Internal Frames in JavaFX