如何在 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>
我得到了一个带有 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>