JTable Zelleninhalt beim Editieren löschen

earlgrey_tea

Aktives Mitglied
Hallo an alle,

Frage:
Wie kann ich in einer JTable einen "excelähnlichen Editiermodus" erreichen, d.h. wenn ich eine Zelle anwähle und hineinschreibe, dann wird alles andere, was voher drinstand gelöscht.

Mein Ansatz:
Ich möchte gerne den TableEditor anpassen. Ich habe dazu auch schon zwei Versuche unternommen, die beide leider fehlgeschlagen sind -- neue Eingaben werden einfach an den alten Inhalt der Zelle angehängt.

Wunsch 🙂
Ich möchte gerne das Konzept hinter JTables und Swing verstehen, deshalb sind Ansätze, wie man sie hier findet für mich eher uninteressant.

Klasse mit Tabelle:
Java:
package tableSelectionTest;

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.JScrollPane;

public class JTableCellEditorTest {

	private JFrame frame;
	private JTable table;

	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					JTableCellEditorTest window = new JTableCellEditorTest();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	public JTableCellEditorTest() {
		frame = new JFrame();
		frame.setBounds(100, 100, 450, 300);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().setLayout(null);
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(49, 27, 265, 160);
		frame.getContentPane().add(scrollPane);
		
		table = new JTable();
		table.setCellSelectionEnabled(true);
		table.setDefaultEditor(String.class, new TextEditor()); 
		table.setModel(new DefaultTableModel(
			new String[][] {
				{"", ""},
				{"", ""},
				{"", ""},
				{"", ""},
			},
			new String[] {
				"New column", "New column"
			}
		));
		scrollPane.setViewportView(table);
	}
}

Erster Versuch CellEditor
Java:
package tableSelectionTest;

import java.awt.Component;

import javax.swing.AbstractCellEditor;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableCellEditor;

@SuppressWarnings("serial")
public class CustomTableCellEditor extends AbstractCellEditor implements
		TableCellEditor {
	
	private JTextField textField;  
	public CustomTableCellEditor(){
		textField = new JTextField();
	}
	
	@Override
	public Component getTableCellEditorComponent(JTable arg0, Object arg1,
			boolean arg2, int arg3, int arg4) {
		textField.setText("Hallo Welt"); 
		textField.selectAll(); 
		return textField;
	}

	@Override
	public Object getCellEditorValue() {
		return textField.getText();
	}

}

Zweiter Versuch CellEditor Quelle
Java:
package tableSelectionTest;

import java.awt.Component;

import javax.swing.DefaultCellEditor;
import javax.swing.JTable;
import javax.swing.JTextField;

public class TextEditor extends DefaultCellEditor {
    public TextEditor() {
       super(new JTextField());
    }

@Override
	public Component getTableCellEditorComponent(JTable table, Object value,
			boolean isSelected, int row, int column) {
		Component c = super.getTableCellEditorComponent(table, value,
				isSelected, row, column);
		((JTextField) getComponent()).selectAll();
		return c;
	}
}
 
Java:
// table.setDefaultEditor(String.class, new TextEditor()); 
table.getColumnModel().getColumn(0).setCellEditor(new CustomTableCellEditor());
 
Vielen Dank! Wenn ich den CellEditor global für die gesamte Tabelle setzen will, muss man folgende Zeile einfügen:

[JAVA=64]table.setDefaultEditor(Object.class, new TextEditor());[/code]

Frage 2
Was läuft jetzt aber in meinem ersten Versuch falsch?

Erster Versuch CellEditor (korrigierter Quellcode)
Java:
import java.awt.Component;
import javax.swing.AbstractCellEditor;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableCellEditor;

@SuppressWarnings("serial")
public class CustomTableCellEditor extends AbstractCellEditor implements
		TableCellEditor {
	
	private JTextField textField;
	
	public CustomTableCellEditor(){
		textField = new JTextField();
	}
	
	@Override
	public Component getTableCellEditorComponent(JTable table, Object value,
			boolean arg2, int arg3, int arg4) {
		textField.setText(String.valueOf(value)); 
		textField.selectAll(); 
		return textField;
	}

	@Override
	public Object getCellEditorValue() {
		return textField.getText();
	}
}
 
Frage 2
Was läuft jetzt aber in meinem ersten Versuch falsch?
Was geht denn nicht?

PS:
Ich würd beim Editor die Border vom Textfeld auf null setzen, dann passt es gut in die Tabellenzelle und der Rahmen (LaF-abhängig) nimmt nicht soviel Platz weg.
Außerdem kannst du dir überlegen die Vorder- und Hintergrundfarbe der Tabelle zu setzen.
 
Ah, ich erinnere mich: Bei mir funktioniert diese Lösung, sprich diese Methode auch noch überschreiben:
Java:
    @Override
    public boolean shouldSelectCell(EventObject anEvent) {
        textField.selectAll();
        return super.shouldSelectCell(anEvent);
    }

Aus der getRendererComp..()-Methode kann das selectAll() dann weg.
 

Zurück
Oben