Excpetion füllen/entleeren von JTable

Raziell

Bekanntes Mitglied
Hallo zusammen,

habe ein Problem beim füllen oder leeren einer JTable. Die Excpetion fliegt manchmal beim befüllen, manchmal beim entleeren und manchmal garnicht.

So in etwa sieht der Stacktrace fast immer aus:

Java:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 2 >= 0
	at java.util.Vector.elementAt(Unknown Source)
	at javax.swing.table.DefaultTableModel.getValueAt(Unknown Source)
	at javax.swing.JTable.getValueAt(Unknown Source)
	at javax.swing.JTable.prepareRenderer(Unknown Source)
	at javax.swing.plaf.synth.SynthTableUI.paintCell(Unknown Source)
	at javax.swing.plaf.synth.SynthTableUI.paintCells(Unknown Source)
	at javax.swing.plaf.synth.SynthTableUI.paint(Unknown Source)
	at javax.swing.plaf.synth.SynthTableUI.update(Unknown Source)
	at javax.swing.JComponent.paintComponent(Unknown Source)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JComponent.paintChildren(Unknown Source)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JViewport.paint(Unknown Source)
	at javax.swing.JComponent.paintChildren(Unknown Source)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JComponent.paintChildren(Unknown Source)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JComponent.paintToOffscreen(Unknown Source)
	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
	at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
	at javax.swing.RepaintManager.paint(Unknown Source)
	at javax.swing.JComponent._paintImmediately(Unknown Source)
	at javax.swing.JComponent.paintImmediately(Unknown Source)
	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
	at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
	at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

Hier mal ein paar Code-Beispiele:

Der Pool hält die Clients und benachrichtigt die GUI.

Java:
ublic class ClientPool extends Observable {

	private static ClientPool instance;
	private CopyOnWriteArrayList<Client> clients = new CopyOnWriteArrayList<Client>();

	private ClientPool() {
	}

	public synchronized static ClientPool getInstance() {
		if (instance == null) {
			instance = new ClientPool();
		}
		return instance;
	}

	public void addClient(Client client) throws SocketException {
		clients.add(client);
		startClientListener(client);
		change();
	}

	private void startClientListener(Client client) {
		new ClientListener(client);
	}

	public void removeClient(Client client) {
		clients.remove(client);
		change();
	}

	private void change() {
		setChanged();
		notifyObservers(clients);
	}

	public CopyOnWriteArrayList<Client> getClients() {
		return clients;
	}

Hier ein paar ausschnitte aus der GUI.

Java:
	@Override
	public void update(Observable o, Object arg) {
		if (arg instanceof StringBuilder) {
			addMessage((StringBuilder) arg);
		} else if (arg instanceof CopyOnWriteArrayList<?>) {
			createTable((CopyOnWriteArrayList<?>) arg);
		}
	}


	@SuppressWarnings("unchecked")
	public void createTable(CopyOnWriteArrayList<?> param) {

		CopyOnWriteArrayList<Client> clients = (CopyOnWriteArrayList<Client>) param;

		model.setRowCount(0);

		for (Client client : clients) {
			model.addRow(client.getDates());
		}

		int j = 1;
		for (int i = 0; i < model.getRowCount(); i++) {
			table.setValueAt("" + j, i, 0);
			j++;
		}
	}

Ich vermute mal das ganze hat iwas. mit der aktualisierung des TableModels zu tun.
Ich verwende das DefaultModel.

Gruß und Danke
 
Datenänderungen der GUI besser nur in
Java:
SwingUtilities.invokeLater(new Runnable() {
  public void run() {
     // Code
  }
});
Blöcken schreiben, aber möglichst kurz, nicht sekundenlange Berechnungen, weil das die GUI blockiert,
rechnen gerne in separaten Threads, die fertigen Ergebnisse auf diesen Weg übertragen,

den Block kann man direkt in Methoden schreiben,
auf lokale Variablen oder Parameter zugreifen, wenn diese als final deklariert sind,
mit den Stichwörtern kann man nach Beispielen suchen
 
Hi,

erstmal danke für die Antwort. Also du meinst das ich quasi Zeile 16-20 in den invokeLater Block
auslagern sollte? Also an den Stellen, an denen ich das Model ändere?

Achso meine GUI ansich läuft bereits mit invokeLater im EDT und lediglich die Methode removeClient kann von mehreren Threads zu jederzeit aufgerufen werden. Die Methode addClient wird nur aus einem einzigen Thread aufgerufen. Vllt. hilft das ja den Fehler einzugrenzen.
 
du hast zwei Code-Blöcke, in beiden klingt Zeile 16-20 nach einem Kandidaten (ok, eher der zweite),
im zweiten Code-Block der spätere Code mit table.setValueAt() ebenso,
was du alles machen musst und wo bei dir welche Threads agieren, kann ich nicht sagen

je mehr vom EDT gemacht wird, desto weniger Exceptions beim painten,
die Gefahr ist lediglich eine blockierte GUI, eben weil vor lauter Arbeit gar keine Zeit mehr zum painten + Ereignisverarbeitung ist
 
Ja ich meinte den zweiten Code-Block 🙂
Also ich werde es heute Abend mal testen und dann berichten was passiert.

Was mich wunder ist, dass die Darstellung der Daten trotz Exception einwandfrei funktioniert und das ich in keinem anderen meiner Programme diesen Fehler hatte, obwohl ich immer das gleiche Prinzip verwendet habe.

Noch erwähnen sollte ich vielleicht, dass der Fehler nur aufgetreten ist, als ich in einer Schleife testweise ca. 50-100 Clients am Server angemeldet habe. Das heisst die update() und die createTable() Methode werden dann halt auch 50-100 mal in kürzester Zeit aufgerufen.
 
Moin,

also sieht so aus als würde es jetzt funktionieren.

Aber nochmal fürs Verständnis: Ist die Exception geflogen, weil der Renderer das Model zeichnet während ich es ändere?
 

Neue Themen


Zurück
Oben