Löschen des Elementes aus der Tabelle durch den Klick auf das Element

barsiq

Mitglied
Hallo,

anbei ein lauffähiges Beispiel einer einspaltigen Tabelle, dessen Zellen aus JComponent's bestehen. Der Klick wird über CellEditor eingeleitet, ein Klick aufs Element löscht ihn aus der Liste.
Versucht es und ihr werdet sehen dass das Verhalten komisch ist. Vor allen Dingen sobald 2 Elemente geblieben sind und das Erste gelöscht wird fällt es implizit auf.

Hat jemand eine Erklärung bzw. ein Fix?

(Klick in den Header macht wieder Zeilen in die Tabelle)

Code:
package test;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractCellEditor;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

public class Frame extends JFrame {

	public static void main(String[] args) {
		Frame f = new Frame();
		f.setVisible(true);
	}
	
	private static final long serialVersionUID = -8531497280636806756L;

	int cellHeight = 30, width = 400;

	Model model;
	JTable table;
	List<Element> list = new ArrayList<Element>();

	public Frame() {
		super();
		setDefaultCloseOperation( EXIT_ON_CLOSE );
		setSize(width,300);

		fillList();

		model = new Model();

		table = new JTable(model);
		JScrollPane jsp = new JScrollPane(table);
		getContentPane().add(jsp, BorderLayout.CENTER);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.setDefaultRenderer(Object.class, new TableCellRenderer(){

			@Override
			public Component getTableCellRendererComponent(JTable table, Object value,
					boolean isSelected, boolean hasFocus, int row, int column) {
				Element e = (Element)table.getValueAt(row, column);
				if (row%2 == 0)
					e.setBackground(Color.WHITE);
				else
					e.setBackground(Color.LIGHT_GRAY);
				return e;
			}

		});

		table.getColumnModel().getColumn(0).setCellEditor(new CellEditor());

		table.getTableHeader().addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent e) {
				if (SwingUtilities.isLeftMouseButton(e)){
					fillList();
					model.fireTableDataChanged();
				}
			}
		});

		table.setRowHeight(cellHeight);
	}

	private void fillList(){
		list.add(new Element("1", width, cellHeight){
			@Override
			void action() {
				list.remove(this);
				model.fireTableDataChanged();				
			}
		});
		list.add(new Element("2", width, cellHeight){
			@Override
			void action() {
				list.remove(this);
				model.fireTableDataChanged();
			}
		});
		list.add(new Element("3", width, cellHeight){
			@Override
			void action() {
				list.remove(this);
				model.fireTableDataChanged();
			}
		});
		list.add(new Element("4", width, cellHeight){
			@Override
			void action() {
				list.remove(this);
				model.fireTableDataChanged();
			}
		});
		list.add(new Element("5", width, cellHeight){
			@Override
			void action() {
				list.remove(this);
				model.fireTableDataChanged();
			}
		});
		list.add(new Element("6", width, cellHeight){
			@Override
			void action() {
				list.remove(this);
				model.fireTableDataChanged();
			}
		});
		list.add(new Element("7", width, cellHeight){
			@Override
			void action() {
				list.remove(this);
				model.fireTableDataChanged();
			}
		});
		list.add(new Element("8", width, cellHeight){
			@Override
			void action() {
				list.remove(this);
				model.fireTableDataChanged();
			}
		});
		list.add(new Element("9", width, cellHeight){
			@Override
			void action() {
				list.remove(this);
				model.fireTableDataChanged();
			}
		});
	}
	abstract class Element extends JComponent {

		private static final long serialVersionUID = 478266331358603585L;

		final String member;
		final JLabel label;
		
		public Element(String m, int breite, int hoehe) {
			super();
			member = m;
			setSize(breite, hoehe);
			label = new JLabel(member);
			label.setBounds(2, 2, getWidth() - 4, getHeight() - 4);
			add(label);
			
			addMouseListener(new MouseAdapter() {
				@Override
				public void mouseReleased(MouseEvent e) {
					if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() > 1){
						System.out.println("Action im " + member);
						action();
					}
				}
			});
		}

		abstract void action();
		
		@Override
		protected void paintComponent(Graphics g) {
			g.setColor(getBackground());
			g.fillRect(0, 0, getWidth(), getHeight());
		}
	}
	class Model extends DefaultTableModel{
		private static final long serialVersionUID = 1L;

		@Override
		public int getRowCount() {
			return list.size();
		}
		@Override
		public int getColumnCount() {
			return 1;
		}
		@Override
		public Object getValueAt(int row, int column) {
			return list.get(row);
		}
		@Override
		public boolean isCellEditable(int row, int column) {
			return true;
		}
	}
	class CellEditor extends AbstractCellEditor implements TableCellEditor {

		private static final long serialVersionUID = 1925480471694428598L;

		public Component getTableCellEditorComponent(JTable table,
				Object value,
				boolean isSelected,
				int row,
				int column) {
			return (Component)table.getValueAt(row, column);
		}

		@Override
		public Object getCellEditorValue() {
			return null;
		}
	}
}
 

barsiq

Mitglied
Tja, es lag daran daß der Editor nach dem Neubilden der Tabelle kein editingStopped abbekommen hat.
Dies erzwinge ich nun mit
Java:
					for (CellEditorListener l : cellEditor.getCellEditorListeners())
						l.editingStopped(new ChangeEvent(this));
und - Wunder - alles geht richtig.

Kompletter Beispiel:
Java:
package test;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractCellEditor;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

public class Frame extends JFrame {

	public static void main(String[] args) {
		Frame f = new Frame();
		f.setVisible(true);
	}
	
	private static final long serialVersionUID = -8531497280636806756L;

	int cellHeight = 30, width = 400;

	Model model;
	JTable table;
	List<Element> list = new ArrayList<Element>();
	CellEditor cellEditor;
	
	public Frame() {
		super();
		setDefaultCloseOperation( EXIT_ON_CLOSE );
		setSize(width,300);

		fillList();

		model = new Model();

		table = new JTable(model);
		JScrollPane jsp = new JScrollPane(table);
		getContentPane().add(jsp, BorderLayout.CENTER);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.setDefaultRenderer(Object.class, new TableCellRenderer(){

			@Override
			public Component getTableCellRendererComponent(JTable table, Object value,
					boolean isSelected, boolean hasFocus, int row, int column) {
				Element e = (Element)table.getValueAt(row, column);
				if (row%2 == 0)
					e.setBackground(Color.WHITE);
				else
					e.setBackground(Color.LIGHT_GRAY);
				return e;
			}

		});

		cellEditor = new CellEditor();
		table.getColumnModel().getColumn(0).setCellEditor(cellEditor);

		table.getTableHeader().addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent e) {
				if (SwingUtilities.isLeftMouseButton(e)){
					fillList();
					model.fireTableDataChanged();
				}
			}
		});

		table.setRowHeight(cellHeight);
	}

	private void fillList(){
		for (char ch : "123456789".toCharArray())
			list.add(new Element(ch + "", width, cellHeight){
				private static final long serialVersionUID = -2640414563083235892L;
				@Override
				void action() {
					list.remove(this);
					model.fireTableDataChanged();
					for (CellEditorListener l : cellEditor.getCellEditorListeners())
						l.editingStopped(new ChangeEvent(this));
				}
			});
	}
	abstract class Element extends JComponent {

		private static final long serialVersionUID = 478266331358603585L;

		final String member;
		final JLabel label;
		
		public Element(String m, int breite, int hoehe) {
			super();
			member = m;
			setSize(breite, hoehe);
			label = new JLabel(member);
			label.setBounds(2, 2, getWidth() - 4, getHeight() - 4);
			add(label);
			
			addMouseListener(new MouseAdapter() {
				@Override
				public void mouseReleased(MouseEvent e) {
					if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() > 1){
						System.out.println("Action im " + member);
						action();
					}
				}
			});
		}

		abstract void action();
		
		@Override
		protected void paintComponent(Graphics g) {
			g.setColor(getBackground());
			g.fillRect(0, 0, getWidth(), getHeight());
		}
	}
	class Model extends DefaultTableModel{
		private static final long serialVersionUID = 1L;

		@Override
		public int getRowCount() {
			return list.size();
		}
		@Override
		public int getColumnCount() {
			return 1;
		}
		@Override
		public Object getValueAt(int row, int column) {
			return list.get(row);
		}
		@Override
		public boolean isCellEditable(int row, int column) {
			return true;
		}
	}
	class CellEditor extends AbstractCellEditor implements TableCellEditor {

		private static final long serialVersionUID = 1925480471694428598L;

		public Component getTableCellEditorComponent(JTable table,
				Object value,
				boolean isSelected,
				int row,
				int column) {
			return (Component)table.getValueAt(row, column);
		}

		@Override
		public Object getCellEditorValue() {
			return null;
		}
	}
}