如何在 javafx 中切换场景(无 FXML)

how to switching scenes in javafx (NO FXML)

初学者请谅解;)

我正在尝试使用 JavaFX 构建一个简单的应用程序。问题是,当我第一次打开 window 时一切顺利,但如果我想更改场景,它会抛出错误...

Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: AnchorPane@1809546[styleClass=root]is already set as root of another scene#

主要class


public class Main extends Application{

    //private Stage primaryStage;

    @Override
public void start(Stage primaryStage) {

    Login login = new Login();
    Scene scene = login.okno();



    primaryStage.setTitle("Komunikator sieciowy JAVA");
    primaryStage.setScene(scene);
    primaryStage.setResizable(false);
    primaryStage.show();

}

    //public Stage getPrimaryStage() {
    //  return this.primaryStage;
    //}

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

登录

public class Login {
    private GridPane grid;
    private Scene scene;
    private Text title;
    private Label nick;
    private Button wejdzBtn;
    private TextField userName;
    //private Alert oknoDlg;




    public Login()  {
        grid = new GridPane();
        grid.setAlignment (Pos.CENTER);
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(25,25,25,25));
        scene = new Scene (grid, 300, 150);
        utworzBtn();
        utworzLogin();
        utworzTekst();
        utworzNick();
        //oknoDialogowe();


    }

    //private void oknoDialogowe()  {
        //Alert oknoDlg = new Alert(Alert.AlertType.CONFIRMATION);
        //oknoDlg.setTitle("Informacja");
        //oknoDlg.setContentText("test");  
    //  oknoDlg.setHeaderText(null);
        //oknoDlg.showAndWait();


    //}

    private void utworzBtn() {
        wejdzBtn = new Button("Zaloguj si\u0119");
        HBox hbBtn = new HBox(10);
        hbBtn.setAlignment (Pos.BOTTOM_RIGHT);
        hbBtn.getChildren().add(wejdzBtn);
        grid.add(hbBtn, 1, 2);
        //wejdzBtn.setDisable(true);
        wejdzBtn.setOnAction(e -> {
            Messages mess = new Messages();
            grid.getScene().setRoot(mess.messa());;
        });

    }

    private void utworzLogin() {

        nick = new Label("Nick:");
        grid.add(nick, 0, 1);
    }

    private void utworzNick() {
        userName = new TextField();
        grid.add(userName,1,1);
        // informacja w polu tekstowym
        userName.setPromptText("Max 15 znak\u00f3w");
        userName.setFocusTraversable(false);

        //maksymalna ilość znaków
        final int maxLength = 15;
        userName.setOnKeyTyped(t -> {
            if (userName.getText().length() > maxLength)
            {
                int pos = userName.getCaretPosition();
                userName.setText(userName.getText(0, maxLength));
                userName.positionCaret(pos);
            }
        });

    }

    private void utworzTekst() {
        title = new Text ("Dzień dobry!");
        title.setFont(Font.font("Calibri", FontWeight.NORMAL, 20));
        grid.add(title, 0, 0, 2, 1);
    }

    public Scene okno() {
        return scene;
    }


}


还有一点 class,我正在尝试使用 login.java

中的按钮进行更改
    public class Messages {
    private AnchorPane anchor;
    private Scene scena;
    //private Label nick;
    private Button sendBtn;
    private TextField poleDoWpisywania;
    private TextArea poleDoWyswietlania, pobierzNick;


    public Messages() {

        anchor = new AnchorPane();
        scena = new Scene(anchor, 700, 600);
        pobierzNick();
        poleDoWpisywania();
        poleDoWyswietlania();
        utworzPrzycisk();

}
    private void utworzPrzycisk() {
        sendBtn = new Button("Wy\u015Blij");
        sendBtn.setDisable(true);

    }

    private void pobierzNick(){
        pobierzNick = new TextArea();
        pobierzNick.setEditable(false);
        pobierzNick.setWrapText(true);
}

    private void poleDoWpisywania() {
    poleDoWpisywania = new TextField();


}

    private void poleDoWyswietlania() {
        poleDoWyswietlania = new TextArea();
        poleDoWyswietlania.setEditable(false);
        poleDoWyswietlania.setWrapText(true);


}


    public Pane messa() {
        return anchor;
}
    }

我可以请你展示修复错误的正确方法吗?

JavaFX 定义了一个场景图,它是一个具有单个根节点的树数据结构。对于您的应用程序(即您发布的代码),根节点是 primaryStage(这是 class Main 中方法 start() 中的参数)。 primaryStage 可以有多个 Scene。每个 Scene 必须有自己的根节点。

您收到的错误消息意味着 Scene 的根不能同时是另一个 Scene 的根。换句话说 anchorscena in class Messages 的根,这意味着它不能设置为 scene in class 的根] Login.

除此之外,如果您想更改 Scene,您需要调用 class Stage 的方法 setScene()。这是您的 Login class 和 Messages class,其中的更改解决了您遇到的 运行 时间错误,并在用户单击时执行场景更改wejdzBtn 按钮。

Login.java
(我只更改了方法 utworzBtn() 中的 lambda 表达式。)

public class Login {
    private GridPane grid;
    private Scene scene;
    private Text title;
    private Label nick;
    private Button wejdzBtn;
    private TextField userName;

    public Login()  {
        grid = new GridPane();
        grid.setAlignment(Pos.CENTER);
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(25,25,25,25));
        scene = new Scene(grid, 300, 150);
        utworzBtn();
        utworzLogin();
        utworzTekst();
        utworzNick();
    }

    private void utworzBtn() {
        wejdzBtn = new Button("Zaloguj si\u0119");
        HBox hbBtn = new HBox(10);
        hbBtn.setAlignment (Pos.BOTTOM_RIGHT);
        hbBtn.getChildren().add(wejdzBtn);
        grid.add(hbBtn, 1, 2);
        wejdzBtn.setOnAction(e -> {
            Messages mess = new Messages();
            Window w = scene.getWindow();
            if (w instanceof Stage) {
                Stage s = (Stage) w;
                s.setScene(mess.getScena());
            }
        });
    }

    private void utworzLogin() {
        nick = new Label("Nick:");
        grid.add(nick, 0, 1);
    }

    private void utworzNick() {
        userName = new TextField();
        grid.add(userName,1,1);
        userName.setPromptText("Max 15 znak\u00f3w");
        userName.setFocusTraversable(false);

        final int maxLength = 15;
        userName.setOnKeyTyped(t -> {
            if (userName.getText().length() > maxLength)
            {
                int pos = userName.getCaretPosition();
                userName.setText(userName.getText(0, maxLength));
                userName.positionCaret(pos);
            }
        });
    }

    private void utworzTekst() {
        title = new Text ("Dzień dobry!");
        title.setFont(Font.font("Calibri", FontWeight.NORMAL, 20));
        grid.add(title, 0, 0, 2, 1);
    }

    public Scene okno() {
        return scene;
    }
}

Messages.java
(我添加了方法getScena()。)

public class Messages {
    private AnchorPane anchor;
    private Scene scena;
    private Button sendBtn;
    private TextField poleDoWpisywania;
    private TextArea poleDoWyswietlania, pobierzNick;

    public Messages() {
        anchor = new AnchorPane();
        scena = new Scene(anchor, 700, 600);
        pobierzNick();
        poleDoWpisywania();
        poleDoWyswietlania();
        utworzPrzycisk();
    }

    private void utworzPrzycisk() {
        sendBtn = new Button("Wy\u015Blij");
        sendBtn.setDisable(true);
    }

    private void pobierzNick() {
        pobierzNick = new TextArea();
        pobierzNick.setEditable(false);
        pobierzNick.setWrapText(true);
    }

    private void poleDoWpisywania() {
        poleDoWpisywania = new TextField();
    }

    private void poleDoWyswietlania() {
        poleDoWyswietlania = new TextArea();
        poleDoWyswietlania.setEditable(false);
        poleDoWyswietlania.setWrapText(true);
    }

    public Scene getScena() {
        return scena;
    }

    public Pane messa() {
        return anchor;
    }
}

非常感谢 Abra,过去 6 个小时我一直在考虑这个问题,但没有注意到这个问题。我也删除了

public Pane messa (); 
return anchor;

我不需要它 ;)