Laden mehrerer FXMLs zur Laufzeit

BlackC

Mitglied
Hallo miteinander,

ich fange gerade an mit JavaFX an und habe ein Problem (wer hätte es gedacht). Ich komme von javafx 1.3.1 und tue mir gerade etwas schwer, dynamisch Klassen meiner Oberfläche zur Laufzeit zu erstellen und anzuzeigen. Hier jetzt erstmal mein Code.

MainView.fxml
[XML]
AnchorPane id="AnchorPane" focusTraversable="true" maxHeight="1080.0" maxWidth="1920.0" minHeight="-Infinity" minWidth="-Infinity" prefHeight="700.0" prefWidth="900.0" xmlns:fx="http://javafx.com/fxml" fx:controller="gui.MainViewController">
<children>
<VBox layoutX="14.0" layoutY="14.0" minHeight="-Infinity" minWidth="-Infinity" prefHeight="672.0" prefWidth="872.0">
<children>
<AnchorPane fx:id="apInfo" prefHeight="50.0" prefWidth="872.0" />
<AnchorPane fx:id="apContent" prefHeight="622.0" prefWidth="872.0" />
</children>
</VBox>
</children>
</AnchorPane>
[/XML]
MainViewController.java
Java:
public class MainViewController implements Initializable {
    
    @FXML
    AnchorPane apInfo ;
    @FXML
    AnchorPane apContent ;  
 
    
    private LoginViewController _loginViewController;
 
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        setLoginView();
    }  
    
    private void setLoginView(){
        try {
            _loginViewController = (LoginViewController) replaceSceneContent("LoginView.fxml");
        } catch (Exception ex) {
            Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private Initializable replaceSceneContent(String fxml) throws Exception {
        FXMLLoader loader = new FXMLLoader();
        InputStream in = Main.class.getResourceAsStream(fxml);
        loader.setBuilderFactory(new JavaFXBuilderFactory());
        loader.setLocation(Main.class.getResource(fxml));
        try {
            apContent  = (AnchorPane) loader.load(in);
        } finally {
            in.close();
        } 
        return (Initializable) loader.getController();
    }
}

Main.java
Java:
public class Main extends Application {
    
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("MainView.fxml"));
        
        Scene scene = new Scene(root);
        
        stage.setScene(scene);
        stage.show();
    }

    /**
     * The main() method is ignored in correctly deployed JavaFX application.
     * main() serves only as fallback in case the application can not be
     * launched through deployment artifacts, e.g., in IDEs with limited FX
     * support. NetBeans ignores main().
     *
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
}

LoginView.fxml
[XML]
AnchorPane id="AnchorPane" fx:id="loginView" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml" fx:controller="gui.LoginViewController">
<children>
<VBox layoutX="14.0" layoutY="14.0" minHeight="270.0" prefHeight="372.0" prefWidth="572.0">
<children>
<GridPane alignment="CENTER" minHeight="-Infinity" minWidth="-Infinity" prefHeight="256.0" prefWidth="572.0">
<children>
<Label fx:id="lFirmenname" alignment="CENTER" contentDisplay="LEFT" text="Firmenname" GridPane.columnIndex="0" GridPane.rowIndex="1" />
<TextField id="tbFirmenname" fx:id="tfFirmenname" prefWidth="200.0" promptText="Firmenname" styleClass="btGeneral" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Label fx:id="lBenutzer" text="Benutzer" GridPane.columnIndex="0" GridPane.rowIndex="2" />
<TextField id="tbBenutzer" fx:id="tfBenutzer" prefWidth="200.0" promptText="Benutzer" styleClass="btGeneral" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label fx:id="lPasswort" text="Passwort" GridPane.columnIndex="0" GridPane.rowIndex="3" />
<PasswordField fx:id="pfPassword" prefWidth="200.0" promptText="Passwort" GridPane.columnIndex="1" GridPane.rowIndex="3" />
</children>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="290.0" minWidth="10.0" prefWidth="286.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="287.0" minWidth="10.0" prefWidth="285.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0">
<children>
<Button fx:id="btLogin" mnemonicParsing="false" text="Anmelden" />
</children>
</VBox>
</children>
</VBox>
</children>
</AnchorPane>
[/XML]

LoginViewController.java
Java:
public class LoginViewController implements Initializable {

    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }    
}

Was möchte ich machen. Ich möchte beim Start meiner Application (später Applet) in apContent (MainView) meine LoginView "draufklatschen" und anzeigen lassen. Später soll dann nach dem erfolgreichen Einloggen andere Klassen auf apContent Platz finden.
Nur bisher bekomme ich nichts angezeigt. An was liegt es ?

Würde mich über eure Hilfe freuen.

Gruß
BlackC
 

Paddelpirat

Bekanntes Mitglied
Hi,

da sind drei Fehler. Die ersten beiden sind die fehlenden
Code:
<
vor AnchorPane in den fxml-Dateien. Der dritte Fehler, wieso du dann nicht deine LoginView siehst, sondern nur ein leeres Fenster ist, dass du in der Main.java den Aufruf

Code:
Parent root = FXMLLoader.load(getClass().getResource("MainView.fxml"));

hast. Hier müsstest du die LoginView.fxml aufrufen.
 

BlackC

Mitglied
Danke für deine Antowrt :)

Mit den fehlenden "<" in den fxmls ist nur ein Kopierfehler ;) . Deine dritte Verbesserung werde ich morgen ausprobieren,da ich da wieder Zugriff auf den Sourceode habe.

Aber ich verstehe es noch nicht ganz. Ich habe meine MainView als Hauptfenster. Wenn ich jetzt beim Start sage, er soll mir die LoginView in das Content-Panel einfügen, müsste es dann nicht angezeigt werden, wenn die MainView gestartet wird ? Wenn ich wie du sagst, die LoginView aufrufe, wird dann nicht nur diese allein angezeigt ?

Gruß

BlackC
 

Paddelpirat

Bekanntes Mitglied
In deiner MainView seh ich aber nicht, wo du die LoginView hinzufügst. Vielleicht bin ich blind, kenne mich aber auch nicht so gut mit fxml aus. Ich habe es bisher in meinen Applikationen so gehandhabt, dass ich zwischendrin die Scene austausche, wenn ich etwas ganz anderes anzeigen möchte.

Sprich ich würde anfangs nur eine Scene mit der LoginView anzeigen und wenn diese erfolgreich bestätigt wird, wechselt das Programm zur Scene mit der MainView.
 

BlackC

Mitglied
Also ich hab deine Änderungen mal umgesetzt und es hat funktioniert, allerdings möchte ich es in meiner MainView anzeigen und nicht als neue scene. Zwar würde es beim Loginschirm noch so gehen, nur hab ich später ein Tabpane, die aus mehreren FXMLs bestehen wird.

Ich hab auch schon etwas im Internet gefunden und versuche es Zeitnah umzusetzen. Wenn es funktioniert, werd ich es hier reinschreiben.

Melde mich auf jedenfall wieder^^


Gruß
BlackC
 

Paddelpirat

Bekanntes Mitglied
Hey,

hab auch gerade nochmal etwas gesucht. Unter dem folgenden Link findest du eine Anleitung für Custom Components. Das dürfte genau das sein, was du suchst:

Introduction to FXML | JavaFX 2.2

Du kannst deine LoginView ja dann auch als custom component erstellen und sie dann ganz normal in eine Scene mit einfügen oder wieder raus nehmen.
 

Neue Themen


Oben