JavaFX中的内部框架

Pet*_*zov 7 javafx javafx-2 javafx-8

我找到了内部框架的这个例子

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

是否可以在JavaFX中创建相同的内部框架?

Ant*_* J. 11

使用JFXtras,有一个Window控件,您可以在其中添加内容并处理内部窗口行为.

首先,您需要在类路径中放入jfxtras库.他们有一些说明,您可以在这里获得图书馆.如果您使用的是maven,只需添加:

<dependency>
    <groupId>org.jfxtras</groupId>
    <artifactId>jfxtras-labs</artifactId>
    <version>2.2-r5</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

或者下载库并将其放入项目类路径中,无论如何.

现在我把Window的演示样本略有不同,允许生成几个窗口.

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);}
}
Run Code Online (Sandbox Code Playgroud)

在原始演示中,事件代码位于init方法中,并且未包含任何按钮.我添加按钮以动态创建窗口并将其添加到屏幕.

以下是应用程序结果的快照:

快照

我完全建议你试试jfxtras的演示.他们真的很棒.希望能帮助到你.


zel*_*lla 9

您可以自己实现简单的内部窗口.主要思想,那个InternalWindow类只是骨架,具有类似功能的内部框架.您可以向其应用任何内容.

1)申报课程

public class InternalWindow extends Region
Run Code Online (Sandbox Code Playgroud)

2)您应该能够在窗口中设置内容

public void setRoot(Node node) {
        getChildren().add(node);
}
Run Code Online (Sandbox Code Playgroud)

3)如果存在多个窗口,您应该能够将窗口带到前面

public void makeFocusable() {    
        this.setOnMouseClicked(mouseEvent -> {
            toFront();
        });    
}
Run Code Online (Sandbox Code Playgroud)

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);
    });
}
Run Code Online (Sandbox Code Playgroud)

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());
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)

结果

在此输入图像描述

完整代码:要点

关于关闭按钮的更新:

您可以向InternalWindow添加方法

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

当构造时:

interalWindow.setCloseButton(closeButton);
Run Code Online (Sandbox Code Playgroud)