JavaFX Applikation lädt Scrollpanes nicht

MARJAVA

Aktives Mitglied
Hallo zusammen,

meine Applikation soll eine Bibliothek werden, die ich mit JavaFX programmieren möchte.
In meinem RootLayout ist im Centerbereich meine "Bücherübersicht"(AnchorPane), die im linken Bereich eine vertikale Scrollpane besitzt, die 5 Regalböden "Regalboden" wiederrum mit 15 Büchern "Buchhalter" als horizontale Scrollpane laden soll.
Ich arbeite mit dem SceneBuilder von Oracle.


Mein Code läuft fehlerfrei, jedoch werden die Scrollpanes nicht angezeigt bzw. geladen.

Ein Bild vom etwaigen Layout und die Javadateien habe ich dazugelegt.

RegalbodenController.java
Java:
import javafx.fxml.FXML;
import javafx.scene.control.ScrollPane;



public class RegalBodenController {

    @FXML
    private ScrollPane scrollpaneRegalboden;
  
    private Main main;
  
    public void setMain(Main main) {
        this.main=main;
    }

    public ScrollPane getScrollPane() {
        scrollpaneRegalboden=new ScrollPane();
        return scrollpaneRegalboden;
    }
  
}

Main.java
Java:
package de.markusc;
  
import java.io.IOException;
import java.util.Vector;

import de.markusc.model.Buch;
import de.markusc.view.BuchUebersichtController;
import de.markusc.view.BuchhalterController;
import de.markusc.view.RegalBodenController;
import de.markusc.view.RootLayoutController;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;


public class Main extends Application {

    private Stage primaryStage;
    private BorderPane rootLayout;
    private ScrollPane buchüberschichtScrollpane,regalbodenScrollpane;
  
    private ObservableList<Buch> buchListe = FXCollections.observableArrayList();
  
    public Main() {
        for(int i=0; i<15;i++) {
            buchListe.add(new Buch("Bauzeichnen", "Zwanzig","Fachbuch","20.03.2018","Libri",623,"9783778256459","Nein","von bis","schön","Es war einmal","pfad"));
        }
    }
  
    public ObservableList<Buch> getPersonData() {
        return buchListe;
    }
  
    @Override
    public void start(Stage primaryStage) {
        try {
            this.primaryStage=primaryStage;
            this.primaryStage.setTitle("Bibliothek");
          
            initRootLayout();
          
            showBooks();
          
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
  


    public void initRootLayout() {
      

      
        try {
          
            FXMLLoader loader= new FXMLLoader();
            loader.setLocation(Main.class.getResource("view/RootLayout.fxml"));
          
          
          
            rootLayout= (BorderPane) loader.load();
          
            Scene scene=new Scene(rootLayout);
            primaryStage.setScene(scene);
          
            RootLayoutController controller = loader.getController();
            controller.setMain(this);
          
            primaryStage.show();
          
          
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
  
    public void showBooks() {
      
        try {
          

          

      

          
          
            // lädt die BücherÜbersicht
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(Main.class.getResource("view/BuchUebersicht.fxml"));
            AnchorPane buchUebersicht = (AnchorPane) loader.load();

            rootLayout.setCenter(buchUebersicht);

            // Give the controller access to the main app.
            BuchUebersichtController controller = loader.getController();
            controller.setMain(this);
            buchüberschichtScrollpane =controller.getScrollpane();
          
          

          
            Vector vregalBoden= new Vector();

            for(int i=0; i<5; i++) {

                FXMLLoader loaderRegalboden = new FXMLLoader();
                loaderRegalboden.setLocation(Main.class.getResource("view/Regalboden.fxml"));
                AnchorPane regalboden = (AnchorPane) loaderRegalboden.load();
              
                RegalBodenController regalbodenController= loaderRegalboden.getController();
                regalbodenController.setMain(this);
                regalbodenScrollpane=regalbodenController.getScrollPane();

              
                vregalBoden.add(regalbodenScrollpane);
              
             
            }
          
            Vector vbuchhalter= new Vector();

            for(int i=0; i<15; i++) {
                FXMLLoader loaderBuchHalter = new FXMLLoader();
                loaderBuchHalter.setLocation(Main.class.getResource("view/BuchHalter.fxml"));
                AnchorPane buchHalter = (AnchorPane) loaderBuchHalter.load();
              
                BuchhalterController buchhalterController=loaderBuchHalter.getController();
              
                buchhalterController.setMain(this);
                buchhalterController.showBook(buchListe.get(i));
              
                vbuchhalter.add(buchHalter);

            }
          
            for(int j=0; j<vregalBoden.size(); j++) {
              
                for(int i=0; i<vbuchhalter.size();i++) {
                    regalbodenScrollpane.setContent((Node) vbuchhalter.get(i));
                }
                buchüberschichtScrollpane.setContent((Node) vregalBoden.get(j));
            }
          

        } catch (IOException e) {
            e.printStackTrace();
        }
      
    }
  
    public static void main(String[] args) {
        launch(args);
    }
}

BuchhalterController.java
Java:
package de.markusc.view;

import de.markusc.Main;
import de.markusc.model.Buch;
import javafx.fxml.FXML;
import javafx.scene.control.Label;

public class BuchhalterController {

    private Main main;
  
    @FXML
    private Label titel;
  
    @FXML
    private Label autor;
  
    @FXML
    private Label seitenzahl;
  
    public void BuchhalterController() {

  
      
    }
    public void setMain(Main main) {
        this.main=main;
    }
  
    public void showBook(Buch buch) {
        if(buch!=null) {
            titel.setText(buch.getTitel().get());
            autor.setText(buch.getAutor().get());
            seitenzahl.setText(String.valueOf(buch.getSeitenzahl().get()));
        }
    }
  
  
}

BuchübersichtController.java
Java:
package de.markusc.view;

import de.markusc.Main;
import javafx.fxml.FXML;
import javafx.scene.control.ScrollPane;

public class BuchUebersichtController {
  
    private Main main;
  
    @FXML
    private ScrollPane scrollpane;
  
    public void setMain(Main main) {
        this.main=main;
    }
  
    public ScrollPane getScrollpane() {
        scrollpane=new ScrollPane();
        return scrollpane;
    }

}
 

Anhänge

  • Bibliothek.JPG
    Bibliothek.JPG
    67,5 KB · Aufrufe: 28
Java:
public ScrollPane getScrollPane() {
    scrollpaneRegalboden=new ScrollPane();
    return scrollpaneRegalboden;
}
Das was du hier zurückgibst ist nicht die ScrollPane die du am Ende siehst (also die du im FXML erstellt hast) sondern eine neue

Wenn du jetzt in deiner Main-Klasse dir über den Controller die ScrollPane beschaffst und wie hier der ScrollPane Elemente hinzufügst, kriegt
das deine ScrollPane (welche angezeigt wird) nicht mit.
Java:
for(int j=0; j<vregalBoden.size(); j++) {
    for(int i=0; i<vbuchhalter.size();i++) {
        regalbodenScrollpane.setContent((Node) vbuchhalter.get(i));
    }
    buchüberschichtScrollpane.setContent((Node) vregalBoden.get(j));
}
 
Deshalb habe ich erwähnt, dass man beim Erstellen einer FXML-Datei ScrollPane nicht als Wurzelelement auswählen kann. Ich vermute mal, dass das funktionale Gründe hat. Genau das müsste bei mir aber zum Wurzelelement werden um es mit dem FXML-Loader anzusprechen und zu laden. Gibt es denn eine alternative zum Laden der ScrollPane, wenn nicht als Wurzelelement?
 
Mein Programm soll die BücherListe auch als xml abspeichern, allerdings erstellt er die Datei nicht korrekt.
Für die Erzeugung nehme ich das Paket JAXB. Ist es erforderlich meine JavaBean-Datei Buch mit einfach Datentypen auszustatten oder geht das auch z.B. mit SimpleStringProperties, was ja zugegebenermaßen bei JavaFX der Standard ist?

Würdet ihr ein anderes Paket empfehlen, bzw. nutzen? Wie ist es dort mit StringProperties?
 
Zuletzt bearbeitet:
Warum nicht einfach eine Getter-Methode bereitstellen und diese annotieren:
Java:
@XmlElement
public Strin getName() {
   return nameProperty().get();
}
 
Das Umstellen auf einen einfachen Datentyp hat funktioniert. Danke
Gibt es andere Pakete die ebenfalls sinn machen oder mehr zu empfehlen sind?
 
MEn kannst du ruhig bei JAXB bleiben. Kann mir kaum vorstellen, dass andere Bibliotheken mit Properties besser umgehen können.
 
Nachdem das Speichern der XML-Datei nun reibungsfrei funktioniert, bekomme ich beim Laden der Datei eine sehr hartnäckige NullpointerException.
Die Liste bekomme ich zurück durch meine WrapperKlasse, in der die richtige Anzahl an Knoten enthalten ist. Jedoch beim Lesen der einzelnen Knotenelemente mit den entsprechenden getter-Methoden wird die Exception geworfen.
Den Code zum Laden habe ich euch mal gepostet:

Java:
    public void loadBuchDataFromFile(File file) {
        try {
            JAXBContext context = JAXBContext
                    .newInstance(BuchListWrapper.class);
            Unmarshaller um = context.createUnmarshaller();

            // Reading XML from the file and unmarshalling.
            BuchListWrapper wrapper = (BuchListWrapper) um.unmarshal(file);

            buchListe.clear();
            buchListe= FXCollections.observableArrayList();
            buchListe.addAll(wrapper.getBuecher());

            // Save the file path to the registry.
            setBuchFilePath(file);
            System.out.println("size: "+buchListe.size());
            System.out.println(((Buch)buchListe.get(0)).getClass());
            for(int i=0;i<buchListe.size();i++) {
                System.out.println(buchListe.getClass());
                System.out.println(((Buch)buchListe.get(i)).getTitel());
            }


        } catch (Exception e) {
            e.printStackTrace();// catches ANY exception
            Alert alert = new Alert(AlertType.ERROR);
            alert.setTitle("Error");
            alert.setHeaderText("Could not load data");
            alert.setContentText("Could not load data from file:\n" + file.getPath());

            alert.showAndWait();
        }
    }
Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<buecher>
    <buch>
        <autor>GI Geoinformatik GmbH (Hrsg.)</autor>
        <cover>/MyLibrary/Images/Books/17.png</cover>
        <isbn>9783879075881</isbn>
        <kategorie>Vermessung</kategorie>
        <kommentar></kommentar>
        <leseZeiten>? - ?</leseZeiten>
        <schlagwort></schlagwort>
        <seitenzahl>889</seitenzahl>
        <status>Nein</status>
        <titel>ArcGIS 10.3</titel>
        <verlag>Wichmann, H</verlag>
        <veroeffentlichung>09/2015</veroeffentlichung>
        <zusfssg></zusfssg>
    </buch>
...
Das entsprechende File ist vorhanden und korrekt.
Doch die Zeile System.out.println(((Buch)buchListe.get(i)).getTitel()); wirft die Exception.
 
Dann schau dir mal an was wrapper.getBuecher() zurückgibt und ob in der Collection überhaupt Elemente vorhanden sind.
 
Habe ich bereits gemacht. Die WrapperKlasse konvertiert die ObservableList erfolgreich in eine Java.Utility.List und speichert sie im XML-Format ab. Das passt soweit. In einem öffentlichen Tutorial wurde diese List aus der WrapperKlasse mittels Methode getBuecher ohne Casting in das Format ObservableList übergeben. Wie gesagt, dieses Tutorial läuft soweit ordentlich und macht keine Probleme. Mit der Methode getClass erhalte ich folgenden Output in der Console:
Code:
C:\Users\Markus Christian\Desktop\test\books2.xml
size: 15
class de.markusc.model.Buch
class com.sun.javafx.collections.ObservableListWrapper
java.lang.NullPointerException
   at de.markusc.model.Buch.getTitel(Buch.java:120)
   at de.markusc.Main.loadBuchDataFromFile(Main.java:377)
   at de.markusc.Main.initRootLayout(Main.java:219)
   at de.markusc.Main.start(Main.java:90)
   at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
   at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
   at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
   at java.security.AccessController.doPrivileged(Native Method)
   at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
   at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
   at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
   at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
   at java.lang.Thread.run(Thread.java:745)

Die Klasse die ich erhalte hat wie oben zu sehen eine size von 15 aber die Exception wird erst in meiner Javabean geworfen.
Die Klasse nennt sich ObservableListWrapper
 
Meine WrapperKlasse sieht wie folgt aus:
Java:
package de.markusc.model;

import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import javafx.collections.ObservableList;


@XmlRootElement(name = "buecher")
public class BuchListWrapper {
   
    private List<Buch> buecher;

    @XmlElement(name = "buch")
    public List<Buch> getBuecher() {
        return buecher;
    }

    public void setBuecher(List<Buch> buecher) {
        this.buecher = buecher;
    }

}

Die Exception wird in meiner Bean geworfen:
Java:
package de.markusc.model;


import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

/**
* Modell Klasse für ein Buch
*
* @author Markus Christian
*
*/
public class Buch {
   
    private StringProperty titel;
    private StringProperty autor;
    private StringProperty kategorie;
    private StringProperty veroeffentlichung;
    private StringProperty verlag;
    private StringProperty seitenzahl;
    private StringProperty isbn;
    private StringProperty status;
    private StringProperty leseZeiten;
    private StringProperty kommentar;
    private StringProperty zusfssg;
    private StringProperty cover;
   
   
   
    public Buch() {
       
    }
   
    public Buch(String titel,String autor,String kategorie, String veroeffentlichung,String verlag,  String seitenzahl, String isbn,String status, String leseZeiten,String kommentar,String zusfssg,String cover) {
        this.titel=new SimpleStringProperty(titel);
        this.autor=new SimpleStringProperty(autor);
        this.kategorie=new SimpleStringProperty(kategorie);
        this.veroeffentlichung=new SimpleStringProperty(veroeffentlichung);
        this.verlag=new SimpleStringProperty(verlag);
        this.seitenzahl=new SimpleStringProperty(seitenzahl);
        this.isbn=new SimpleStringProperty(isbn);
        this.status=new SimpleStringProperty(status);
        this.leseZeiten=new SimpleStringProperty(leseZeiten);
        this.kommentar=new SimpleStringProperty(kommentar);
        this.zusfssg=new SimpleStringProperty(zusfssg);
        this.cover=new SimpleStringProperty(cover);
       
       
    }
    public String getKommentar() {
        return kommentar.get();
    }

    public void setKommentar(String kommentar) {
        this.kommentar.set(kommentar);;
    }


    public String getLeseZeiten() {
        return leseZeiten.get();
    }

    public void setLeseZeiten(String leseZeiten) {
        this.leseZeiten.set(leseZeiten);
    }

    public String getZusfssg() {
        return zusfssg.get();
    }

    public void setZusfssg(String zusfssg) {
        this.zusfssg.set(zusfssg);
    }

    public String getCover() {
        return cover.get();
    }

    public void setCover(String cover) {
        this.cover.set(cover);
    }

    public void setTitel(String titel) {
        this.titel.set(titel);
    }

    public void setAutor(String autor) {
        this.autor.set(autor);
    }

    public void setKategorie(String kategorie) {
        this.kategorie.set(kategorie);
    }

    public void setVeroeffentlichung(String veroeffentlichung) {
        this.veroeffentlichung.set(veroeffentlichung);
    }

    public void setIsbn(String isbn) {
        this.isbn.set(isbn);
    }

    public void setVerlag(String verlag) {
        this.verlag.set(verlag);
    }

    public void setSeitenzahl(String seitenzahl) {
        this.seitenzahl.set(seitenzahl);
    }

    public void setSchlagwort(String schlagwort) {
        this.kommentar.set(schlagwort);
    }

    public void setStatus(String status) {
        this.status.set(status);
    }

    public String getTitel() {
        return titel.get();
    }
   

    public String getAutor() {
        return autor.get();
    }

    public String getKategorie() {
        return kategorie.get();
    }

    public String getVeroeffentlichung() {
        return veroeffentlichung.get();
    }

    public String getIsbn() {
        return isbn.get();
    }

    public String getVerlag() {
        return verlag.get();
    }

    public String getSeitenzahl() {
        return seitenzahl.get();
    }

    public String getSchlagwort() {
        return kommentar.get();
    }

    public String getStatus() {
        return status.get();
    }
   
    public String getZusammenfssg() {
        return zusfssg.get();
    }
   

}
 
Das scheint der fall zu sein. Doch dann muss ich wieder die Frage stellen, ob die Wrapperklasse mit Properties umgehen kann oder ob sie einfache Datentypen benötigt. Die XML-Datei ist soweit korrekt, aber das Tutorial arbeitet auch mit properties. Also sollte das nicht stören. Doch tiefer in die Wrapperklasse kann ich nicht hinein, da es sich dabei dann eher um die Implementierung der JaxBmethode dreht, oder?
 
An sich sollte es ausreichen, wenn du im default-Konstruktor die ganzen Properties einfach initialisierst.
Java:
public Buch() {
   this.title = new SimpleStringProperty("");
   ...
}
 
Jetzt klappts🙂🙂🙂

Ich musste den Standardkontruktor so anpassen, dass die Javabean kein Null erzeugt.
Es scheint so zu sein, dass die Wrapperklasse den Standardkontruktor nutzt.🙂🙂🙂

Seufz, diese Idee hatte ich gerade beim Surfen auch bekommen

Danke Robat
 

Zurück
Oben