# JTable einzelne Zellen selektieren



## redbomber (30. Nov 2008)

Hallo zusammen, ich habe noch eine weitere Frage:

Im meiner Tabelle können die unterschiedlichen Zellen per Mausklick selektiert werden, die selektierten Zellen markiere ich mit einem X. (Also mir drawLine in der paint() Methode)

Nun gibt es aber das Problem, dass wenn ich Zellen in der ersten Zeile markieren und dann eine Zelle in der zweiten Zeile markiere, plötzlich alle markierungen die Zeile wechseln.

Also waren in Zeile 1 die Zellen 4,5 und 6 markiert, so sind bei klick auf Zeile 2 plötzlich in der Zeile 2 die entsprechenden Zellen markiert. Hüpft also immer hin und her, je nachdem welche Zeile ich angeklickt habe.

Irgend jemand eine Idee woran das liegen kann?


----------



## André Uhres (30. Nov 2008)

Bitte mach mal ein kurzes, selbständiges, kompilierbares Besipiel.


----------



## redbomber (3. Dez 2008)

Leider nicht seh kurz, aber dieser Code veranschaulicht mein Problem:
Ich kann also nicht einzelne Zelen föllig frei selektieren. Die markierten Zellen springen immer in die Zeile in der ich mich gerade befinde.
Ich habe allerdings gelesen dass: 

NOTE: JTable uses a very simple concept of selection, managed as an intersection of rows and columns. It was not designed to handle fully independent cell selections.
java.sun.com/docs/books/tutorial/uiswing/components/table.html



```
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel;



public class SimpleTable
 {
	public static String[][] rowData = { { "Japan", "245", "245" }, { "USA", "240", "245" },
		{ "Italien", "220", "245" }, { "Spanien", "217", "245" },
		{ "Türkei", "215", "245" }, { "England", "214", "245" },
		{ "Frankreich", "190", "245" }, { "Griechenland", "185", "245" },
		{ "Deutschland", "180", "245" }, { "Portugal", "170", "245" } };
	public static String[] columnNames = { "Land",
		"Durchschnitt", "Age" };
	public static boolean isFrame = true;
	public static void main(String[] args) {

		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JTable table = new JTable(rowData, columnNames);
		TableModel model = new SimpleTableModel();
		table.setModel(model);
		table.setBackground(Color.WHITE);
		// ändert Größe der gesamten Tabelle (nur Sinnvoll falls JTable in
		// JScrollPane)
		table.setAutoResizeMode(0);
		// Setze JTable sichtbar
		table.setVisible(true);
		// Umordnung der Spalten nicht erlaubt
		table.getTableHeader().setReorderingAllowed(false);

		// erlaubt Selektion der Elemente in einer Reihe
		table.setRowSelectionAllowed(true);
		// erlaubt Selektion der Elemente in einer Spalte
		table.setColumnSelectionAllowed(true);
		// hier wird festgelegt wie die Werte in der Tabelle selektiert werden
		// dürfen
		table.getSelectionModel().setSelectionMode(
				ListSelectionModel.SINGLE_SELECTION);

		BoxRenderer boxRenderer = new BoxRenderer();
		table.setDefaultRenderer(Object.class, boxRenderer);

		JScrollPane scrollPane = new JScrollPane(table);
		frame.add(scrollPane, BorderLayout.CENTER);
		frame.pack();
		frame.setVisible(true);

	}
}

final class SimpleTableModel extends AbstractTableModel{

	public static String[][] rowData = { { "Japan", "245", "245" }, { "USA", "240", "245" },
		{ "Italien", "220", "245" }, { "Spanien", "217", "245" },
		{ "Türkei", "215", "245" }, { "England", "214", "245" },
		{ "Frankreich", "190", "245" }, { "Griechenland", "185", "245" },
		{ "Deutschland", "180", "245" }, { "Portugal", "170", "245" } };
	public static String[] columnNames = { "Land",
		"Durchschnitt", "Age" };
	
	SimpleTableModel(){
		
	}
	
	public boolean isCellEditable(int row, int col){
		return false;
	}
	
	public void setValueAt(Object value, int row, int col){
		
	}
	
	@Override
	public int getColumnCount() {
		
		return 3;
	}

	@Override
	public int getRowCount() {
		// TODO Auto-generated method stub
		return 10;
	}

	@Override
	public Object getValueAt(int row, int col) {
		// TODO Auto-generated method stub
		return rowData[row][col];
	}
	
}

final class BoxRenderer extends DefaultTableCellRenderer{

	public static String[][] rowData = { { "Japan", "245", "245" }, { "USA", "240", "245" },
		{ "Italien", "220", "245" }, { "Spanien", "217", "245" },
		{ "Türkei", "215", "245" }, { "England", "214", "245" },
		{ "Frankreich", "190", "245" }, { "Griechenland", "185", "245" },
		{ "Deutschland", "180", "245" }, { "Portugal", "170", "245" } };
	public static String[] columnNames = { "Land",
		"Durchschnitt", "Age" };
	
	protected boolean isSelected;
	@Override
	public Component getTableCellRendererComponent(JTable table, Object value,
			boolean isSelected, boolean hasFocus, int row, int col) {
		// TODO Auto-generated method stub
		
		this.isSelected = isSelected;
		
		return this;
	}

	public void paint(Graphics g) {
		super.paint(g);
		// paint cross onto selected cell 
		if (isSelected) {
			g.setColor(Color.RED);
			g.drawLine(0, 0, getWidth(), getHeight());
			g.drawLine(0, getHeight(), getWidth(), 0);
		}
	}
	
}
```


----------



## André Uhres (3. Dez 2008)

Wir können die Selektionen in einer Liste speichern, die wir dem Renderer übergeben:

```
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.table.*;
public class SimpleTable {
    private String[][] rowData = {{"Japan", "245", "245"}, {"USA", "240", "245"},
        {"Italien", "220", "245"}, {"Spanien", "217", "245"},
        {"Türkei", "215", "245"}, {"England", "214", "245"},
        {"Frankreich", "190", "245"}, {"Griechenland", "185", "245"},
        {"Deutschland", "180", "245"}, {"Portugal", "170", "245"}
    };
    private String[] columnNames = {"Land",
        "Durchschnitt", "Age"
    };
    private JTable table;
    private SimpleTableModel model;
    private List<String> selections;
    public SimpleTable() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        table = new JTable();
        model = new SimpleTableModel(rowData, columnNames);
        table.setModel(model);
        // ändert Größe der gesamten Tabelle (nur Sinnvoll falls JTable in
        // JScrollPane)
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        // Umordnung der Spalten nicht erlaubt
        table.getTableHeader().setReorderingAllowed(false);
        // erlaubt Selektion der Elemente in einer Reihe
        table.setRowSelectionAllowed(true);
        // erlaubt Selektion der Elemente in einer Spalte
        table.setColumnSelectionAllowed(true);
        // hier wird festgelegt wie die Werte in der Tabelle selektiert werden
        // dürfen
        table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        selections = new ArrayList<String>();
        table.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(final MouseEvent e) {
                int row = table.getSelectedRow();
                int column = table.getSelectedColumn();
                String key = row + "," + column;
                if (selections.contains(key)) {
                    selections.remove(key);
                } else {
                    selections.add(key);
                }
                table.repaint();
            }
        });
        BoxRenderer boxRenderer = new BoxRenderer(selections);
        table.setDefaultRenderer(Object.class, boxRenderer);
        JScrollPane scrollPane = new JScrollPane(table);
        frame.add(scrollPane, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(final String[] args) {
        Runnable gui = new Runnable() {
            @Override
            public void run() {
                new SimpleTable();
            }
        };
        SwingUtilities.invokeLater(gui);
    }
}
final class SimpleTableModel extends AbstractTableModel {
    private String[][] rowData;
    private String[] columnNames;
    SimpleTableModel(final String[][] rowData, final String[] columnNames) {
        this.rowData = rowData;
        this.columnNames = columnNames;
    }
    @Override
    public String getColumnName(final int column) {
        return columnNames[column];
    }
    @Override
    public boolean isCellEditable(final int row, final int col) {
        return false;
    }
    @Override
    public int getColumnCount() {
        return 3;
    }
    @Override
    public int getRowCount() {
        return 10;
    }
    @Override
    public Object getValueAt(final int row, final int col) {
        return rowData[row][col];
    }
}
final class BoxRenderer extends DefaultTableCellRenderer {
    private List<String> selections;
    private String key;
    public BoxRenderer(final List<String> list) {
        selections = list;
    }
    @Override
    public Component getTableCellRendererComponent(final JTable table, final Object value,
            final boolean isSelected, final boolean hasFocus, final int row, final int col) {
        super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
        key = row + "," + col;
        return this;
    }
    @Override
    public void paintComponent(final Graphics g) {
        super.paintComponent(g);
        // paint cross onto selected cell
        for (String entry : selections) {
            if (entry.equals(key)) {
                g.setColor(Color.RED);
                g.drawLine(0, 0, getWidth(), getHeight());
                g.drawLine(0, getHeight(), getWidth(), 0);
            }
        }
    }
}
```


----------



## redbomber (7. Dez 2008)

Vielen Dank, das hat soweit geklappt!

Möchte ich nun aber die Selektion mehrerer Zellen nur durch gedrückthalten der STRG Taste erlauben, so komme ich zu folgendem Code:


```
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.table.*;
public class SimpleTable {
    private String[][] rowData = {{"Japan", "245", "245"}, {"USA", "240", "245"},
        {"Italien", "220", "245"}, {"Spanien", "217", "245"},
        {"Türkei", "215", "245"}, {"England", "214", "245"},
        {"Frankreich", "190", "245"}, {"Griechenland", "185", "245"},
        {"Deutschland", "180", "245"}, {"Portugal", "170", "245"}
    };
    private String[] columnNames = {"Land",
        "Durchschnitt", "Age"
    };
    private JTable table;
    private SimpleTableModel model;
    private List<String> selections;
    public SimpleTable() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        table = new JTable();
        model = new SimpleTableModel(rowData, columnNames);
        table.setModel(model);
        // ändert Größe der gesamten Tabelle (nur Sinnvoll falls JTable in
        // JScrollPane)
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        // Umordnung der Spalten nicht erlaubt
        table.getTableHeader().setReorderingAllowed(false);
        // erlaubt Selektion der Elemente in einer Reihe
        table.setRowSelectionAllowed(true);
        // erlaubt Selektion der Elemente in einer Spalte
        table.setColumnSelectionAllowed(true);
        // hier wird festgelegt wie die Werte in der Tabelle selektiert werden
        // dürfen
        table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        selections = new ArrayList<String>();
        table.addMouseListener(new MouseAdapter() {
        	@Override
        	public void mouseClicked(MouseEvent e){
        		if(e.getButton() == MouseEvent.BUTTON1){
        			int row = table.getSelectedRow();
                    int column = table.getSelectedColumn();
                    String key = row + "," + column;
                    System.out.println("Key " + key);
        			int mods = e.getModifiersEx();
        			mods &= MouseEvent.CTRL_DOWN_MASK;
        			
        			// überprüfen ob STRG gedrückt wird
					if (mods != 0) {
						// toggle selection of the clicked probe
						// or select the probe
						  if (selections.contains(key)) {
			                    selections.remove(key);
			                } else {
			                    selections.add(key);
			                }
					} else {
						// select only one probe
						selections.clear();
						selections.add(key);

					}
					table.repaint();
        		}
        		
        	}
        });
        BoxRenderer boxRenderer = new BoxRenderer(selections);
        table.setDefaultRenderer(Object.class, boxRenderer);
        JScrollPane scrollPane = new JScrollPane(table);
        frame.add(scrollPane, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(final String[] args) {
        Runnable gui = new Runnable() {
            @Override
            public void run() {
                new SimpleTable();
            }
        };
        SwingUtilities.invokeLater(gui);
    }
}
final class SimpleTableModel extends AbstractTableModel {
    private String[][] rowData;
    private String[] columnNames;
    SimpleTableModel(final String[][] rowData, final String[] columnNames) {
        this.rowData = rowData;
        this.columnNames = columnNames;
    }
    @Override
    public String getColumnName(final int column) {
        return columnNames[column];
    }
    @Override
    public boolean isCellEditable(final int row, final int col) {
        return false;
    }
    @Override
    public int getColumnCount() {
        return 3;
    }
    @Override
    public int getRowCount() {
        return 10;
    }
    @Override
    public Object getValueAt(final int row, final int col) {
        return rowData[row][col];
    }
}

final class BoxRendererNew extends JPanel implements TableCellRenderer{
	private List<String> selections;
    private String key;
    public BoxRendererNew(final List<String> selections) {
        this.selections = selections;
    }
	@Override
	public Component getTableCellRendererComponent(JTable arg0, Object arg1,
			boolean arg2, boolean arg3, int arg4, int arg5) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
    public void paintComponent(final Graphics g) {
        super.paintComponent(g);
        // paint cross onto selected cell
        for (String entry : selections) {
            if (entry.equals(key)) {
                g.setColor(Color.RED);
                g.drawLine(0, 0, getWidth(), getHeight());
                g.drawLine(0, getHeight(), getWidth(), 0);
            }
        }
    }
	
}

final class BoxRenderer extends DefaultTableCellRenderer {
    private List<String> selections;
    private String key;
    public BoxRenderer(final List<String> selections) {
        this.selections = selections;
    }
    @Override
    public Component getTableCellRendererComponent(final JTable table, final Object value,
            final boolean isSelected, final boolean hasFocus, final int row, final int col) {
        super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
        key = row + "," + col;
        return this;
    }
    @Override
    public void paintComponent(final Graphics g) {
        super.paintComponent(g);
        // paint cross onto selected cell
        for (String entry : selections) {
            if (entry.equals(key)) {
                g.setColor(Color.RED);
                g.drawLine(0, 0, getWidth(), getHeight());
                g.drawLine(0, getHeight(), getWidth(), 0);
            }
        }
    }
}
```


Hier gibt es dann jedoch ein neues Problem:

Habe ich bereits in der ersten Spalte eine Zelle markiert und möchte nun noch weitere Zellen aus der zweiten oder dritten Spalte markieren, so wwerden lediglich Zellen der ersten Spalte selektiert/deselektiert.
Auffällig ist dabei, dass durch gedrückthalten der STRG Taste nicht nur eine Zelle blau markiert ist, sondern es ist gleich die ganze Zeile blau markiert.

Gibt es vielleicht eine Default belegung für die STRG Taste?


----------



## redbomber (9. Dez 2008)

hat keiner eine Idee woran das liegen kann?


----------



## Oli (9. Dez 2008)

Hi,

table.setSelectionMode(2);
table.setColumnSelectionAllowed(false);
table.setRowSelectionAllowed(false);
table.setCellSelectionEnabled(true);

so lassen sich einzelne Zellen auswählen. Mit STRG kann man auch mehrere auswählen

Grüße


----------



## redbomber (9. Dez 2008)

Hallo, vielen Dank!!

Das werde ich gleich ausprobieren.

```
table.setColumnSelectionAllowed(false);
table.setRowSelectionAllowed(false);
```
habe ich beides bisher noch auf true.


```
table.setSelectionMode(2);
```
 habe ich bisher noch auf SINGLE_SELECTION.
ich schreib dann nochmal ob es geklappt hat.



Allerdings habe ich auch gerade eine andere Lösung für mein Problem gefunden.
Bisher hatte ich es wie folgt implementiert:


```
public void mouseClicked(MouseEvent e) {
				// TODO Auto-generated method stub
				// falls die linke Maustaste gedrückt wurde
				if (e.getButton() == MouseEvent.BUTTON1) {
                                        int row = getSelectedRow();
					int column = getSelectedColumn();
					
}
```

Dabei habe ich festgestellt, dass 
	
	
	
	





```
getSelectedColumn()
```
 oft die falsche Spalte ausspuckt, bzw. einfach die Spalte in der ich die erste Zelle markiert hatte.

Ersetzt man das ganze zu:


```
public void mouseClicked(MouseEvent e) {
				// TODO Auto-generated method stub
				// falls die linke Maustaste gedrückt wurde
				if (e.getButton() == MouseEvent.BUTTON1) {
                                       int row = rowAtPoint(e.getPoint());
					int column = columnAtPoint(e.getPoint());
					
}
```

Erhalte ich die richtigen Spalten und Zeilen und alles klappt so wie es sein soll.


----------

