如何在 JavaFX 中将容器从一个 window 转移到另一个

How to transfer a container from one window to another in JavaFX

我得到了一个带有 onclick 方法的名为“Transfer”的按钮和一个包含 3 个按钮的 VBox window。 第二个 window 只有一个 HBox 容器。 我想了解如何通过按下传输按钮将 VBox 发送到另一个 window 中的 HBox。

关于我的 code/file 组织的反馈也有帮助。

主要Class:

package testproject;
import javafx.application.Application;
import testproject.screen1.Screen1;
import testproject.screen2.Screen2;
import javafx.stage.Stage;

public class Main extends Application {

private Screen1 screen1;
private Screen2 screen2;

@Override
public void start(Stage primaryStage) throws Exception{

    screen1 = new Screen1(this, new Stage());
    screen2 = new Screen2(this, primaryStage);
}
public static void main(String[] args) {
    Application.launch(args);
}
}

屏幕 1 Class:

package testproject.screen1;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import testproject.Main;
import java.io.IOException;

public class Screen1 {

public Screen1(Main main, Stage stage){

    FXMLLoader loader = new FXMLLoader();
 
  try {
        Parent root = 
        loader.load(getClass().getResourceAsStream("/testproject/screen1/screen1.fxml"));
        stage.setTitle("Screen 1");
        stage.setScene(new Scene(root, 300, 275));
    }
    catch (IOException e) {
        e.printStackTrace();
    }
    stage.show();
}
}

屏幕 2 Class:

package testproject.screen2;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import testproject.Main;
import java.io.IOException;

public class Screen2 {

public Screen2(Main main, Stage stage) {

    FXMLLoader loader = new FXMLLoader();

    try {

        Parent root =        
   loader.load(getClass().getResourceAsStream("/testproject/screen2/screen2.fxml"));
        stage.setTitle("Screen 2");
        stage.setScene(new Scene(root, 300, 275));
    }
    catch (IOException e) {
        e.printStackTrace();
    }

    stage.show();
}
}

Screen1Controller Class:

package testproject.screen1;

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;

public class Screen1Controller {

@FXML
private AnchorPane Pane1;
@FXML
private VBox VBoxScreen1;
@FXML
private Button TransferButton;
@FXML
void transferToScreen2(MouseEvent event){
}
}

Screen2Controller Class:

package testproject.screen2;
import javafx.fxml.FXML;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;

public class Screen2Controller {

@FXML
private AnchorPane Pane2;
@FXML
private HBox HBoxScreen2;
 }

我能想到的一种方法是将 callback/consumer 传递给 screen2 控制器,让它知道如何处理它的节点。话虽如此,可以有许多其他方法来满足此要求。

根据我的看法,您不需要单独的 类 来加载屏幕。您可以查看下面的工作演示。

Main.java

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        FXMLLoader loader2 = new FXMLLoader(getClass() .getResource("screen2.fxml"));
        VBox screen2 = loader2.load();
        Screen2Controller screen2Controller = loader2.getController();
        Stage screen2Stage = new Stage();
        Scene scene2 = new Scene(screen2);
        screen2Stage.setScene(scene2);
        screen2Stage.setTitle("Screen 2");
        screen2Stage.setX(900);
        screen2Stage.setY(100);
        screen2Stage.show();

        FXMLLoader loader1 = new FXMLLoader(getClass() .getResource("screen1.fxml"));
        VBox screen1 = loader1.load();
        Screen1Controller screen1Controller = loader1.getController();
        // Set a consumer to the screen1 to let it know what to do
        screen1Controller.setTransferer(screen2Controller::moveNode);
        Scene scene1 = new Scene(screen1);
        primaryStage.setScene(scene1);
        primaryStage.setTitle("Screen 1");
        primaryStage.setX(100);
        primaryStage.setY(100);
        primaryStage.show();
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}

Screen1Controller.java

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import java.util.function.Consumer;

public class Screen1Controller {

    @FXML
    private VBox pane1;
    @FXML
    private VBox vBoxScreen1;
    @FXML
    private Button transferButton;
    private Consumer<Node> transferer;

    @FXML
    void transferToScreen2(ActionEvent event) {
        // First remove the node from the parent.
        pane1.getChildren().remove(vBoxScreen1);

        // Then send the node to do the other operation.
        this.transferer.accept(vBoxScreen1);
    }

    public void setTransferer(Consumer<Node> transferer) {
        this.transferer = transferer;
    }
}

screen1.fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<VBox fx:id="pane1" xmlns="http://javafx.com/javafx"
           xmlns:fx="http://javafx.com/fxml"
           fx:controller="com.Whosebug.javafx.issue7.Screen1Controller"
           prefHeight="400.0" prefWidth="600.0" spacing="10">
    <children>
        <VBox fx:id="vBoxScreen1" spacing="10" style="-fx-border-width:2px;-fx-border-color:red;-fx-background-color:yellow;" prefWidth="200" maxWidth="200" prefHeight="200">
            <children>
                <Button text="Button 1"/>
                <Button text="Button 2"/>
                <Button text="Button 3"/>
            </children>
            <padding>
                <Insets topRightBottomLeft="10" />
            </padding>
        </VBox>
        <Button fx:id="transferButton" text="Transfer" onAction="#transferToScreen2"/>
    </children>
    <padding>
        <Insets topRightBottomLeft="10" />
    </padding>
</VBox>

Screen2Controller.java

import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;

public class Screen2Controller {

    @FXML
    private VBox pane2;
    @FXML
    private HBox hBoxScreen2;

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

screen2.fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<VBox fx:id="pane2" xmlns="http://javafx.com/javafx"
      xmlns:fx="http://javafx.com/fxml"
      fx:controller="com.Whosebug.javafx.issue7.Screen2Controller"
      prefHeight="400.0" prefWidth="600.0" spacing="10">
    <children>
        <HBox fx:id="hBoxScreen2" spacing="10">
            <padding>
                <Insets topRightBottomLeft="10" />
            </padding>
        </HBox>
    </children>
    <padding>
        <Insets topRightBottomLeft="10" />
    </padding>
</VBox>