[Erledigt] JTable: Rows entfernen und danach Row selektieren

Hallo!

Hab mal wieder ein Problem mit der JTable.

:smiley:


Ich hab eine Methode, die alle markierten Reihen meiner JTable uploadTable entfernt:

		int[] remRows = uploadTable.getSelectedRows();
		for (int row : remRows) {
			tableModel.removeRow(row);
		}
}```

Jetzt möchte ich, dass nach dem Entfernen die Reihe selektiert ist, die nach der letzten zu löschenden Reihe kam.

**Beispiel:**
Vorher:
[IMG]http://www.abload.de/img/table-vorher1xz.png[/IMG]
Nachher:
[img]http://www.abload.de/img/table-nachher3b0.png[/img]
(gefärbt = selektiert)

Ich habe schon einige Stunden rumgebastelt, aber immer hatte der Code einen Haken...

Kann mir jemand helfen?

Gruß,
pcworld
PS: Ich schau mal, was ich noch an gebrauchbarem Code habe, um es euch nicht so schwer zu machen.

Ich würde das löschen aller Zeilen komplett im model machen, wo es auch hingehört :wink:

public int removeRows(int[] rows) {
    int row;
    for(row : rows) {
        // let us assume our data stored in a list
        m_rows.remove(row);
    }
    return(row + 1);
}

Das von Deiner Tabelle aus aufrufen und der zurückgegebene int-wert ist die Zeile nach der zu letzt gelöschten.

Gut Schuß
VuuRWerK :wink:

Wenn ich deine Methode deleteSelectedRows ausbaue, komme ich auf sowas:

    int[] remRows = uploadTable.getSelectedRows();
    int nextRow = remRows[remRows.length - 1] + 1;
    uploadTable.changeSelection(nextRow, 0, false, false);
    for (int row = remRows.length - 1; row > -1; row--) {
        tableModel.removeRow(remRows[row]);
    }
}```

@Andre: Das hatte ich auch erst als lösung jedoch dachte ich wäre es doch von Vorteil gleich noch zu erwähnen das sowas ins Model selbst gehört :wink:

Gut Schuß
VuuRWerK :wink:

Hab jetzt mal folgenden Code zusammengebracht:

			remRows = uploadTable.getSelectedRows();

			System.out.print("remRows: ");
			for (int row : remRows) {
				System.out.print(row + " ");
			}
			System.out.println();

			int lastSelectedRow = remRows[remRows.length - 1];

			uploadTable.changeSelection(lastSelectedRow + 1, uploadTable
					.getSelectedColumn(), false, false);

			SwingUtilities.invokeLater(new Runnable() {
				@Override
				public void run() {
					for (int row : remRows) {
						System.out.println("remove row: " + row);
						tableModel.removeRow(row);
					}
				}
			});
}```

Jedoch kommt da folgende Ausgabe mit Exception:

remRows: 0 1 3
remove row: 0
remove row: 1
remove row: 3
Exception occurred during event dispatching:
java.lang.ArrayIndexOutOfBoundsException: 3 >= 3
at java.util.Vector.removeElementAt(Unknown Source)
at javax.swing.table.DefaultTableModel.removeRow(Unknown Source)
at gui.GUI$RemoveRowsListener$1.run(GUI.java:414)



Und wird da auch nicht alles korrekt gelöscht.
**Vorher:**
[IMG]http://www.abload.de/img/table-vorhercnx.png[/IMG]

**Nachher:**
[IMG]http://www.abload.de/img/table-nachher3q6.png[/img]

Wie man sieht, dürften eigentlich nur "C" und "E" übrig bleiben - so ist es aber nicht.

**Das Problem:**
In dem Moment, wenn eine Row gelöscht wird, ändern sich die Indexes und es werden die falschen Rows gelöscht...

Leider finde ich im **DefaultTableModel** nur ****eine**** [removeRow()-Methode](http://java.sun.com/javase/6/docs/api/javax/swing/table/DefaultTableModel.html#removeRow(int)), der man **einen** Integer übergeben kann, aber keine mit einem Integer-Array.

Gibt es trotzdem eine Aushilfe?
Klar, mit rumrechnen würde es gehen, aber ich hoffe, es geht einfacher...

Gruß,
pcworld

Hab grad was von André gefunden, ich probier’s mal aus: http://www.java-forum.org/de/viewtopic.php?p=432210#432210

Gruß,
pcworld

Edit:
Es kommt auf’s gleiche raus.

						System.out.println("remove row: " + row);
						int rowInModel = uploadTable
								.convertRowIndexToModel(remRows[row]);
						tableModel.removeRow(rowInModel);
}```

Bitte beachte: gelöscht wird immer in umgekehrter Reihenfolge, dann verändern sich die Indexes nicht.

Super, es funktioniert! Danke!

				int rowInModel = uploadTable.convertRowIndexToModel(remRows**);
				tableModel.removeRow(rowInModel);
}```

Gruß,
pcworld

Hab den Code jetzt nochmal so erweitert, dass wenn die letzte Row selektiert ist, die vorletzte Reihe markiert wird.

			int[] remRows = uploadTable.getSelectedRows();
			int lastSelectedRow = remRows[remRows.length - 1];
			int lastRow = uploadTable.getRowCount() - 1;
			int selectedCol = uploadTable.getSelectedColumn();

			if (lastRow > lastSelectedRow) {
				uploadTable.changeSelection(lastSelectedRow + 1, selectedCol,
						false, false);
			} else if (lastRow == lastSelectedRow) {
				uploadTable.changeSelection(lastSelectedRow - 1, selectedCol,
						false, false);
			}

			for (int i = remRows.length - 1; i > -1; i--) {
				int rowInModel = uploadTable.convertRowIndexToModel(remRows**);
				tableModel.removeRow(rowInModel);
			}
}```

Das funktioniert soweit.

Hab jetzt aber noch ein Problem:

**Vorher:**
[img]http://www.abload.de/img/table-vorherktj.png[/img]

**Nachher:**
[img]http://www.abload.de/img/table-nachherlho.png[/img]

Es ist keine Row selektiert!

**Das Problem:**
Es wird die Reihe über der letzten selektierten Reihe markiert, nämlich so, wie es im Code steht... - und die wird dann gelöscht. Dann ist natürlich keine Row mehr markiert!

Hab schon ein bisschen rumprobiert (s. [hier](http://nopaste.byte-welt.de/view.php?id=565)), konnte dieses Problem allerdings noch nicht lösen.

Könnt ihr mir weiterhelfen?

Gruß,
pcworld

Probiers doch so, merk dir die kleinste markierte Zeile und die -1 markierst du nach dem Löschen.

Funktioniert nicht immer.
Beispiel:

Vorher:

Nachher:

Sowas scheinbar einfaches ist gar nicht so einfach, wie man auf den ersten Blick denkt…

Gruß,
pcworld

Die Problemfälle treten ja ein, wenn vor dem Löschen die letzte Zeile selektiert ist.
Wir können dann einen boolean “selectLastRow” auf “true” setzen.
Nach dem Löschen selektieren wir in dem Fall einfach die letzte Zeile der Tabelle.

Hab es jetzt endlich hingekriegt… - damit ich an diesem Code nie mehr was ändern muss, und ich ihn mir hoffentlich nicht mehr ansehen muss, habe ich JTable erweitert…

Ich glaub, das ist einen Wiki-Beitrag wert :slight_smile:


import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

public class MyJTable extends JTable {

	public MyJTable(TableModel model) {
		setModel(model);
	}

	public void deleteSelectedRows() {
		if (!(getModel() instanceof DefaultTableModel)) {
			throw new UnsupportedOperationException(
					"The TableModel must be a instance of DefaultTableModel.");
		}

		DefaultTableModel model = (DefaultTableModel) getModel();

		int lastRow = getRowCount() - 1;
		ArrayList<Integer> remRows = new ArrayList<Integer>();
		for (int row : getSelectedRows()) {
			remRows.add(row);
		}
		boolean isAllSelected = ((remRows.size() - 1) == lastRow);

		if (remRows.size() == 0) {
			return;
		}

		int lastSelectedRow = remRows.get(remRows.size() - 1);
		int selectedColumn = getSelectedColumn();

		int selectRow = -1;
		boolean erfolg = false;
		if (lastRow == lastSelectedRow && !isAllSelected) {
			selectRow = lastSelectedRow;
			while (!erfolg) {
				erfolg = true;
				selectRow--;
				if (remRows.contains(selectRow)) {
					erfolg = false;
				}
			}

		} else if (lastSelectedRow < lastRow) {
			selectRow = lastSelectedRow;
			while (!erfolg) {
				selectRow++;
				erfolg = true;
				if (remRows.contains(selectRow)) {
					erfolg = false;
				}
			}
		}
		changeSelection(selectRow, selectedColumn, false, false);

		// Rows löschen
		for (int i = remRows.size() - 1; i > -1; i--) {
			int rowInModel = convertRowIndexToModel(remRows.get(i));
			model.removeRow(rowInModel);
		}
	}
}```

Hey,
das geht auch viel einfacher als du denkst. Ich hatte auch vor kurzem das selbe Problem.

ich gib dir einfach mal die Lösung und es erklärt sich von selbst denke ich ^^


//Es ist wichtig dass du getRow() zu einer variable zuweißt, denn nach jedem durchgang verändert sie sich ja. Es Funktioniert in kleineren Fällen auch ohne eine Variable aber mach es lieber mit.
    if(jTableAusgabeModel.getRowCount()>=1) // Ich wollte die erste Zeile immer behalten, als Spalten name sozusagen           {    
                for(int i=0;i<rows;i++)
                ((DefaultTableModel) jTableAusgabeModel).removeRow(0);
            }```

@Unregistriert:
Dein Code ist so viel ich weiß nur dazu da, um tatsächlich die Reihen zu entfernen.
Mir ging es darum, dass nach dem Entfernen einer Reihe noch irgendwo der Fokus auf einer Reihe liegt, und das möglichst sinnvoll.