Swing Komisches Problem mit TableModel & setAutoCreateRowSorter

hdi

Top Contributor
EDIT: Mal wieder ein Fall von "Ich stell ne Frage und komme dadurch auf die Lösung" 😉

Problem war dass ich nicht einfach table.repaint() machen kann. Der Table hält intern wohl gewisse Parameter, die sich nur anpassen wenn echte ModelEvents gefeuert werden (um effizient zu zeichnen schätze ich).

Habe also table.repaint() ausgetauscht mit:
Code:
table.tableChanged(new TableModelEvent(table.getModel()));

Jetzt funzt alles. Sorry für Spam 😀

Hey,

Habe hier grad ein Problem, dass ich nicht nachvollziehen kann: Table mit nem Model implements TableModel, setAutoCreateRowSorter(true). Das Sortieren funzt auch, allerdings fängt das TableModel bzw der Controller an zu spinnen sobald mal sortiert wurde: Die Methoden des TableModels werden entweder gar nicht mehr aufgerufen oder nicht mehr über den gesamten Datenraum hinweg.

Untiges KSKB zeigt was ich meine. Das Problem ist nochmal als Comment bei der getValueAt beschrieben.

Zum besseren Verständnis startet bitte die Demo und macht folgendes: Fügt ein paar Datensätze hinzu, klickt die Spalte zum Sortieren an, und fügt weitere hinzu. Ihr werdet sehen, das bei anschließendem Hinzufügen neuer Daten die getRowCount Methode nicht mehr aufgerufen wird. Erst wenn man nochmal auf die Spalte klickt, und wieder etwas hinzufügt wird sie aufgerufen. Sie liefert dann auch den richtigen (aktuellen) Wert. Aber die getValue() wird trotzdem nur noch über dem alten Datenraum (Indizies) aufgerufen.

Hat jmd eine Ahnung was da los ist? Danke

Java:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

public class KSKB extends JFrame {

	public static void main(String[] args) {
		new KSKB().setVisible(true);
	}

	KSKB() {
		setDefaultCloseOperation(EXIT_ON_CLOSE);

		final JTable table = new JTable(new Model());
		table.setPreferredSize(new Dimension(500, 500));

		JButton button = new JButton("Add data");
		button.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				Model m = (Model) table.getModel();
				m.data.add("Data # " + (m.data.size() + 1));
				table.repaint();
			}
		});

		table.setAutoCreateRowSorter(true);

		setLayout(new BorderLayout());
		add(new JScrollPane(table));
		add(button, BorderLayout.SOUTH);
		pack();
	}

	class Model implements TableModel {

		private List<Object> data = new ArrayList<Object>();

		@Override
		public int getRowCount() {
			System.out
					.println("getRowCount invoked, returning: " + data.size());
			return data.size();
		}

		@Override
		public int getColumnCount() {
			return 1;
		}

		@Override
		public String getColumnName(int columnIndex) {
			return "Column";
		}

		@Override
		public Class<?> getColumnClass(int columnIndex) {
			return String.class;
		}

		@Override
		public boolean isCellEditable(int rowIndex, int columnIndex) {
			return false;
		}

		/*
		 * !!! After sorting for a column, and then adding new data, this method
		 * is no longer invoked! after clicking a column header again, it is
		 * invoked again - but only with indices for the old data - tough
		 * getRowCount() returns the right value!
		 */
		@Override
		public Object getValueAt(int rowIndex, int columnIndex) {
			System.out.println("getValueAt invoked, returning: "
					+ data.get(rowIndex));
			return data.get(rowIndex);
		}

		@Override
		public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
		}

		@Override
		public void addTableModelListener(TableModelListener l) {
		}

		@Override
		public void removeTableModelListener(TableModelListener l) {
		}

	}
}
 
Zuletzt bearbeitet:
Danke, ich weiß schon 😉 Mir ist bewusst dass man das normalerweise eh anders aufzieht, zB feuert man das TableModelEvent nicht direkt an der Stelle, wo man den Button geklickt hat, sondern indirekt über die ModelListener. Aber ich hab grad etwas mit MVC rumgespielt, und da Swing das leider zum Großteil recht undurchschaubar kapselt und kein echtes MVC implementiert wollte ich versuchen auf alle Hilfestützen von Swing zu verzichten und das komplett selbst implementieren.
 

Zurück
Oben