java.lang.IndexOutOfBoundsException:

dior

Bekanntes Mitglied
Hi,

ich fülle eine TableView mit Daten aus einer DB.
Das ganze läuft auch gut solange ich keine Daten abrufen die mehr Spalten hat als die Vorherige.
Beispiel:
1. Abfrage hat 30 Spalten. Das Ergebnis wird angezeigt.
2. Abfrage hat 16 Zeilen. Wenn ich diese starte kommt:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index: 16, Size: 16
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)

Wenn ich zuerst die mit 16 Zeilen Ausführe und dann die mit 30 kommt kein Fehler.

Hier der Code der Methode in der der Fehler passiert:
Java:
public void buildData() {
      //  tableview1.getItems().clear();
     
        data = FXCollections.observableArrayList();
       System.out.println("index: " + data.indexOf(c));
    //   System.out.println("index: " + row.indexOf(row));
        try {
            c = DB._DB_Connection.getConnection();
            System.out.println("real SQL: " + SQL);
            ResultSet rs = c.createStatement().executeQuery(SQL);
            TableColumn col = new TableColumn();
            // data.clear();
           
           
            /* TABLE COLUMN ADDED DYNAMICALLY */
            for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
               
                //We are using non property style for making dynamic table
                final int j = i;
                col = new TableColumn(rs.getMetaData().getColumnName(i + 1));
                col.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList, String>, ObservableValue<String>>() {
                    public ObservableValue<String> call(TableColumn.CellDataFeatures<ObservableList, String> param) {
                        return new SimpleStringProperty(param.getValue().get(j).toString());
                    }
                });

                int rowNr = i + 1;
                System.out.println("Column [" + rowNr + "] " + rs.getMetaData().getColumnName(rowNr));
                tableview1.getColumns().addAll(col);
            }
            /* Data added to ObservableList */
            //int zeile = 1;  // Wert für ExcelExport
            while (rs.next()) {

                row = FXCollections.observableArrayList();
                for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
                    Object o = rs.getObject(i);
                    row.add(o == null ? "" : o.toString()); // wenn ein NULL Value gefunden wird, wird dieser durch "" ersetzt
                }
                data.addAll(row);
            }
                      
            tableview1.setItems(data);
            ausgabe1.setText("" + data.size());
            System.out.println("Anzahl der Zeilen: " + data.size());
            System.out.println("index: " + data.indexOf(data));
            System.out.println("indexTableView: " + data.indexOf(tableview1));
            System.out.println("index: " + row.indexOf(row));

            // Rechtsklick in TableView initialisieren!
            RechtsKlickMenue();

            rs.close();
            c.close();

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Error on Building Data");
        }

    }
 
Der StackTrace sagt dir genau in welcher Zeile dieser Fehler auftritt, leider hast du nicht den vollständigen StackTrace gepostet und auch nicht gezeigt bei welcher Zeile der Fehler auftritt.
Ansonsten ist die Fehlermeldung eindeutig: Du greifst auf einen Index zu den es nicht gibt. Warum wieso weshalb können wir nur raten da uns die genaue Fehlerquelle nicht gesagt wurde. Aber mittels Debugger sollte es dir auch selber möglich sein herauszufinden warum wieso weshalb 🙂
 
Hier die komplette Exception:

die Zeilen 144 - 146 sind diese hier (= FXMLDocumentController.java):
Java:
col.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList, String>, ObservableValue<String>>() {
                    public ObservableValue<String> call(TableColumn.CellDataFeatures<ObservableList, String> param) {
                        return new SimpleStringProperty(param.getValue().get(j).toString());

Java:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index: 16, Size: 16
    at java.util.ArrayList.rangeCheck(ArrayList.java:653)
    at java.util.ArrayList.get(ArrayList.java:429)
    at com.sun.javafx.collections.ObservableListWrapper.get(ObservableListWrapper.java:89)
    at FX.FXMLDocumentController$1.call(FXMLDocumentController.java:146)
    at FX.FXMLDocumentController$1.call(FXMLDocumentController.java:144)
    at javafx.scene.control.TableColumn.getCellObservableValue(TableColumn.java:578)
    at javafx.scene.control.TableColumn.getCellObservableValue(TableColumn.java:563)
    at javafx.scene.control.TableCell.updateItem(TableCell.java:644)
    at javafx.scene.control.TableCell.indexChanged(TableCell.java:468)
    at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116)
    at com.sun.javafx.scene.control.skin.TableRowSkinBase.requestCellUpdate(TableRowSkinBase.java:659)
    at com.sun.javafx.scene.control.skin.TableRowSkinBase.lambda$init$497(TableRowSkinBase.java:159)
    at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
    at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:105)
    at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
    at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
    at javafx.scene.control.Cell.setItem(Cell.java:403)
    at javafx.scene.control.Cell.updateItem(Cell.java:670)
    at javafx.scene.control.TableRow.updateItem(TableRow.java:259)
    at javafx.scene.control.TableRow.indexChanged(TableRow.java:225)
    at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116)
    at com.sun.javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1957)
    at com.sun.javafx.scene.control.skin.VirtualFlow.addLeadingCells(VirtualFlow.java:1246)
    at com.sun.javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1194)
    at com.sun.javafx.scene.control.skin.VirtualFlow.setCellCount(VirtualFlow.java:231)
    at com.sun.javafx.scene.control.skin.TableViewSkinBase.updateRowCount(TableViewSkinBase.java:567)
    at com.sun.javafx.scene.control.skin.VirtualContainerBase.checkState(VirtualContainerBase.java:113)
    at com.sun.javafx.scene.control.skin.VirtualContainerBase.layoutChildren(VirtualContainerBase.java:108)
    at com.sun.javafx.scene.control.skin.TableViewSkinBase.layoutChildren(TableViewSkinBase.java:696)
    at javafx.scene.control.Control.layoutChildren(Control.java:576)
    at javafx.scene.Parent.layout(Parent.java:1087)
    at javafx.scene.Parent.layout(Parent.java:1093)
    at javafx.scene.Parent.layout(Parent.java:1093)
    at javafx.scene.Parent.layout(Parent.java:1093)
    at javafx.scene.Parent.layout(Parent.java:1093)
    at javafx.scene.Parent.layout(Parent.java:1093)
    at javafx.scene.Parent.layout(Parent.java:1093)
    at javafx.scene.Parent.layout(Parent.java:1093)
    at javafx.scene.Scene.doLayoutPass(Scene.java:552)
    at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2397)
    at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354)
    at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:381)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
    at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
    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)
 
Java:
    return new SimpleStringProperty(param.getValue().get(j).toString());

Ich gehe davon aus du du hier mit "get(j)" auf einen nicht vorhanden Index zugreifen willst.
Überlege und versuche herauszufinden warum dort mittels falschen Index zugegriffen wird, vielleicht gibt es wo einen Denkfehler und das Problem lässt sich so lösen. Leider lässt sich nicht erkennen woher "j" kommt, wo wird der Wert dieser Variable gesetzt usw.
 
Ich weise j=i aus der For-Schleife zu:
Java:
for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
               
                 //We are using non property style for making dynamic table
                 final int j = i;
 
Stimmt übersehen 😉
Aber ja ändert nichts an der Tatsache das du bei diesem "CellValueFactory" Dings mit einen falschen Index zugreifst. Warum kann ich dir nicht genau sagen da ich damit noch nicht gearbeitet habe.
Wirf den Debugger an und kontrolliere um was für ein Objekt es sich bei "param" handelt. Was bekommst du zurück mit getValue()? Wieviele Elemente enthält dieses Objekt?
 
param.getValue() beinhaltet die einzelnen Zeilen der DB Abfrage.
frage wie ich die Werte da wieder löschen kann wenn ich eine neue Abfrage mache.
 
Ok, ich verstehe deinen Code weitgehend. Du willst dynamisch Tabellen aus einer DB und deren Spalten Anzeigen. Korrekt?

Ich vermute, dass das Problem einfach dadurch entsteht, dass du zuerst die Spalten (TableColumn) anlegst und bereits mit noch nicht vorhandenen Daten verknüpfst (obwohl ich dachte, dass das erst relevant ist, wenn man tatsächlich Daten anzeigen muss). Die JavaFX-Tabelle wird ja bereits initialisiert/geupdatet, wenn du "tableview1.getColumns().addAll(col);" ausführst. Aber ich bin mir nicht zu 100% sicher, dass ich es richtig verstanden habe.

Des weiteren verstehe ich aber noch nicht deinen Code für die eigentlichen Daten. Du liest die Row in eine Liste ein und fügst diese dann den Daten mit #addAll hinzu. Ist deine Tabelle so etwas wie "TableView<List<String>>"?

Wann passiert das eigentlich? Erst beim zweiten Durchlauf der SQL Query? Wenn ja, dann müsstest du vielleicht vorher die Daten (und evtl. auch die TableColumns) clearen.
 
Die Daten sind in einer ObservableList

public static ObservableList<ObservableList<String>> data = FXCollections.observableArrayList();
public static ObservableList<String> row = FXCollections.observableArrayList();
 
Noch etwas ist mir aufgefallen....
Wenn ich
Java:
tableview1.setItems(data);
auskommtentiere dann kommt keine IndexOutOfBounndsException. Natürlich werden auch keine Daten in der TableView angezeigt.

Ich müsste also "nur" die TableView vorher wieder leeren, aber ich bekomme das nicht hin, leider....
 
"tableview1.getItems().clear()" - das ist am Ende auch nur eine List-Implementierung.
Und eventuell auch noch "tableview1.getColumns().clear()" vorher, damit alle Spalten wirklich neu gemacht werden (wenn notwendig).

Im Prinzip dort, wo der Teil am Anfang deiner #buildData()-Methode auskommentiert steht...

Noch etwas fällt mir auf: Ich vermute, dass deine Oberfläche auch noch kurz "einfriert", oder? Denn so wie es aussieht, machst du die DB-Operation auf dem UI-Thread (stelle dir gerade vor, wie ich einen Seufzer von mir gebe und mit dem Kopf schüttel 😉).
Wenn dein Problem behoben ist, solltest du das in einen eigenen Thread auslagern (z.B. in einem JavaFX-Task).
 
Danke für die Hilfe!

Aber ich komme noch immer nicht ganz zurecht... ich habe jetzt
Java:
public void buildData() {
      tableview1.getItems().clear();
      tableview1.getColumns().clear();
      
       System.out.println("index: " + data.indexOf(c));
        try {
            c = DB._DB_Connection.getConnection();
            System.out.println("real SQL: " + SQL);
            ResultSet rs = c.createStatement().executeQuery(SQL);
            TableColumn col = new TableColumn();
.
.
.

und bekomme beim 2. mal Ausführen einer Abfrage nichtmehr die IndexOutOfBoundsException sondern:
Exception in thread "JavaFX Application Thread" java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at java.util.AbstractList$Itr.remove(AbstractList.java:374)
at java.util.AbstractList.removeRange(AbstractList.java:571)
at java.util.AbstractList.clear(AbstractList.java:234)
at FX.FXMLDocumentController.buildData(FXMLDocumentController.java:123)
at FX.FXMLDocumentController$2.changed(FXMLDocumentController.java:466)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.ReadOnlyObjectPropertyBase.fireValueChangedEvent(ReadOnlyObjectPropertyBase.java:74)
at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:102)
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
at javafx.scene.control.SelectionModel.setSelectedItem(SelectionModel.java:102)
at javafx.scene.control.MultipleSelectionModelBase.lambda$new$34(MultipleSelectionModelBase.java:67)
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.ReadOnlyIntegerPropertyBase.fireValueChangedEvent(ReadOnlyIntegerPropertyBase.java:72)
at javafx.beans.property.ReadOnlyIntegerWrapper.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:102)
at javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:113)
at javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:147)
at javafx.scene.control.SelectionModel.setSelectedIndex(SelectionModel.java:68)
at javafx.scene.control.MultipleSelectionModelBase.select(MultipleSelectionModelBase.java:404)
at javafx.scene.control.MultipleSelectionModelBase.clearAndSelect(MultipleSelectionModelBase.java:356)
at javafx.scene.control.TreeView$TreeViewBitSetSelectionModel.clearAndSelect(TreeView.java:1477)
at com.sun.javafx.scene.control.behavior.CellBehaviorBase.simpleSelect(CellBehaviorBase.java:256)
at com.sun.javafx.scene.control.behavior.CellBehaviorBase.doSelect(CellBehaviorBase.java:220)
at com.sun.javafx.scene.control.behavior.CellBehaviorBase.mousePressed(CellBehaviorBase.java:150)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:95)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:388)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
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)
 
Java:
(122) public void buildData() {
(123)      tableview1.getItems().clear();
(124)      tableview1.getColumns().clear();
 
Ok, dann fällt mir gerade nichts mehr dazu ein. Wie wird #buildData() aufgerufen? Die erste Runde im initialize und die Zweite manuell?
 
Ich habe eine TreeView mit ein paar Einträgen.
Beide male rufe ich die Abfrage "manuell" auf.

Java:
TreeItem<String> uwsw = new TreeItem<>("USW");
TreeItem<String> gasHA = new TreeItem<>("GHA");

Java:
/* *************************************************************************************************
        ** Action Event wenn Auswahl in TreeView getroffen wurde
        ************************************************************************************************** */
        treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {

            @Override
            public void changed(ObservableValue observable, Object oldVal, Object newVal) {
                System.out.println(oldVal + " neuer: " + newVal);

                switch (newVal.toString()) {
case "TreeItem [ value: USW ]":
                        sqlDatei = "USW.txt";
                        xlsxSheetName = sqlDatei.substring(0, sqlDatei.lastIndexOf('.'));
                        // xlsxDateiName = xlsxDateiName + sqlDatei.substring(0, sqlDatei.lastIndexOf('.')) + ".xlsx";
                        pIVisible();
                        AuswahlClicked();
                        buildData();
                        Platform.runLater(() -> new TableFilter(tableview1));
                        ;
                        break;
case "TreeItem [ value: GHA ]":
                        sqlDatei = "gha.txt";
                        AuswahlClicked();
                        buildData();
                        Platform.runLater(() -> new TableFilter(tableview1));
                       
                        break;
.
.
.
 
Jetzt hab ich es... nach dem kopieren vom letzten code:

Platform.runLater(() -> new TableFilter(tableview1));

muss aus der TreeView weg, dann klappt es 🙂

DANKE
 

Neue Themen


Zurück
Oben