# Java JTable - Combobox + Checkbox - Cellrenderer + Editor



## Developer_X (16. Nov 2014)

Hallo liebes Forum,

Ich habe eine JTable, welche Beschriftungen in der linken Spalte, und verschiedene JComponents in der rechten Spalte enthält (JTextFields, JCheckBoxes für Boolean und JComboboxes für Integer)
Ich habe dazu meinen eigenen Cellrenderer erstellt, doch wenn ich versuche, z.B. die Checkbox anzucklicken, um den Wert zu ändern, erscheint an der Stelle ein TextField.

Also habe ich versucht meinen eigenen CellEditor zu programmieren, einen für Checkboxes und einen für Comboboxes, dies hat nicht funktioniert, also habe ich einen für beide geschrieben, aber dies funktioniert ebenfalls nicht.

Kann mir bitte jemand helfen?

Danke, 
Developer_X


```
String[] columnNames =
                {"", ""};

                Object[][] data =
                {
                        { "A", ""},
                        { "B", ""},
                        { "C", new Integer(0)     },
                        { "D", new Boolean(true)  },
                        { "E", "A.B.C" },
                        { "F", new Integer(0)  }
                };

                JTable table = new JTable(data, columnNames)
                {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public boolean isCellEditable(int row, int column)
                    {
                        if(column==0)
                            return false;
                        else
                            return true;
                    }
                };
                table.setRowSelectionAllowed(false);
                table.setColumnSelectionAllowed(false);
                table.setCellSelectionEnabled(false);
                table.setPreferredScrollableViewportSize(table.getPreferredSize());
                table.setDefaultRenderer( Object.class,  new FormalDataCellRenderer(table.getDefaultRenderer(Object.class)));
                table.setDefaultRenderer( Boolean.class, new FormalDataCellRenderer(table.getDefaultRenderer(Boolean.class)));
                table.setDefaultRenderer( Integer.class, new FormalDataCellRenderer(table.getDefaultRenderer(Integer.class)));

                table.setDefaultEditor(Object.class, new FormalDataCellEditor(table.getCellEditor()));
```


```
public class FormalDataCellRenderer implements TableCellRenderer
{
    private TableCellRenderer normal;

    public FormalDataCellRenderer(TableCellRenderer cellRenderer)
    {
        super();
        this.normal = cellRenderer;
    }

    public Component getTableCellRendererComponent(JTable table,Object value, boolean isSelected, boolean hasFocus, int row,int column)
    {
        if(column==1)
        {
            if(value instanceof Boolean)
            {
                return new JCheckBox("",value.equals(new Boolean(true)));
            }
            else if(value instanceof Integer)
            {
                JComboBox<String> typeSelection = new JComboBox<String>();
                typeSelection.addItem(sm.getString(StringConstants.PROFILE_GENDER_MALE));
                typeSelection.addItem(sm.getString(StringConstants.PROFILE_GENDER_FEMALE));
                typeSelection.setSelectedIndex((Integer)(value));
                return typeSelection;
            }
        }
        return normal.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    }
}
```


```
public class FormalDataCellEditor extends DefaultCellEditor
{
    public FormalDataCellEditor(TableCellEditor editor)
    {
        super(new JCheckBox()); //? What shall I do?
    }

    @Override
    public Component getTableCellEditorComponent(JTable table,Object value, boolean isSelected, int row, int column)
    {
        if(column==1)
        {
            System.out.println(value.toString());

            if(value instanceof Boolean)
            {
                if(value.equals(new Boolean(true)))
                {
                    value = new Boolean(false);
                }
                else
                {
                    value = new Boolean(true);
                }
                return new JCheckBox("",value.equals(new Boolean(true)));
            }
            else if(value instanceof Integer)
            {
                JComboBox<String> typeSelection = new JComboBox<String>();
                typeSelection.addItem(sm.getString(StringConstants.PROFILE_GENDER_MALE));
                typeSelection.addItem(sm.getString(StringConstants.PROFILE_GENDER_FEMALE));

                int selected = (Integer)(value);
                if(selected<typeSelection.getItemCount()-1)
                    selected++;
                else
                    selected = 0;
                typeSelection.setSelectedIndex(selected);
                value = new Integer(selected);

                return typeSelection;
            }
        }
        return super.getTableCellEditorComponent(table, value, isSelected,row, column);
    }
}
```


----------



## Developer_X (17. Nov 2014)

Hier auch nochmal ein passendes KSKB für alle, die mir
so vielleicht schneller und besser helfen können / wollen.


```
package test;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.util.LinkedList;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

public class EasyExample
{
//  Attributes

//  Constructor
    public EasyExample()
    {
    }

//  Methods
    public static void main(String[] args)
    {
        Dimension screen = java.awt.Toolkit.getDefaultToolkit().getScreenSize();

        JFrame frame = new JFrame();

        frame.setTitle("Table Example");        
        frame.setSize(screen.width/4, screen.height/2);
        frame.setLocationRelativeTo(null);

        frame.setLayout(new BorderLayout());
        JPanel Panel = new JPanel();
        Panel.setLayout(new BoxLayout(Panel,BoxLayout.Y_AXIS));
        frame.add(Panel,"Center");

        JPanel formalData = new JPanel();
        formalData.setBorder(BorderFactory.createTitledBorder("Formal Data"));
        formalData.setLayout(new BorderLayout());
        Panel.add(formalData);

        String[] columnNames = {"", ""};
        Object[][] data =
        {
           { "A", ""},
           { "B", ""},
           { "C", new Integer(0)},
           { "D", new Boolean(true)},
           { "E", "A.B.C" },
           { "F", "Rhababer"}
        };

        JTable table = new JTable(data, columnNames)
        {
            private static final long serialVersionUID = 1L;

            public boolean isCellEditable(int row, int column)
            {
                if(column==0)
                    return false;
                else
                    return true;
            }
        };

        table.setRowSelectionAllowed(false);
        table.setColumnSelectionAllowed(false);
        table.setCellSelectionEnabled(false);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        table.setDefaultRenderer( Object.class,  new FormalDataCellRenderer(table.getDefaultRenderer(Object.class)));
        table.setDefaultRenderer( Boolean.class, new FormalDataCellRenderer(table.getDefaultRenderer(Boolean.class)));
        table.setDefaultRenderer( Integer.class, new FormalDataCellRenderer(table.getDefaultRenderer(Integer.class)));

        table.setDefaultEditor(Object.class, new FormalDataCellEditor(table.getCellEditor()));

        formalData.add(new JScrollPane(table));

        frame.setVisible(true);
    }

    static class FormalDataCellRenderer implements TableCellRenderer
    {
        private TableCellRenderer normal;

        public FormalDataCellRenderer(TableCellRenderer cellRenderer)
        {
            super();
            this.normal = cellRenderer;
        }

        public Component getTableCellRendererComponent(JTable table,Object value, boolean isSelected, boolean hasFocus, int row,int column)
        {
            if(column==1)
            {
                if(value instanceof Boolean)
                {
                    return new JCheckBox("",value.equals(new Boolean(true)));
                }
                else if(value instanceof Integer)
                {
                    JComboBox<String> typeSelection = new JComboBox<String>();
                    typeSelection.addItem("male");
                    typeSelection.addItem("female");
                    typeSelection.setSelectedIndex((Integer)(value));
                    return typeSelection;
                }
            }
            return normal.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        }
    }

    static class FormalDataCellEditor extends DefaultCellEditor
    {
        public FormalDataCellEditor(TableCellEditor editor)
        {
            super(new JCheckBox()); //? What shall I do?
        }

        @Override
        public Component getTableCellEditorComponent(JTable table,Object value, boolean isSelected, int row, int column)
        {
            if(column==1)
            {
                if(value instanceof Boolean)
                {
                    if(value.equals(new Boolean(true)))
                    {
                        value = new Boolean(false);
                    }
                    else
                    {
                        value = new Boolean(true);
                    }
                    return new JCheckBox("",value.equals(new Boolean(true)));
                }
                else if(value instanceof Integer)
                {
                    JComboBox<String> typeSelection = new JComboBox<String>();
                    typeSelection.addItem("male");
                    typeSelection.addItem("female");

                    int selected = (Integer)(value);
                    if(selected<typeSelection.getItemCount()-1)
                        selected++;
                    else
                        selected = 0;
                    typeSelection.setSelectedIndex(selected);
                    value = new Integer(selected);

                    return typeSelection;
                }
            }
            return super.getTableCellEditorComponent(table, value, isSelected,row, column);
        }
    }
}
```


----------



## X5-599 (17. Nov 2014)

Ich habe mal schnell das hier zusammengeworfen. Es scheint! zu funktionieren...


```
package test.table;

import java.awt.BorderLayout;
import java.awt.Component;

import javax.swing.AbstractCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;


public class TableTest
{
	static class CustomIntegerCellEditor extends AbstractCellEditor implements TableCellEditor
	{
		private static final long serialVersionUID = -6114257434861790170L;
		
		private JComboBox<String> combo = new JComboBox<String>();
		
		public CustomIntegerCellEditor(String[] values)
		{
			for(String value : values)
				this.combo.addItem(value);
		}
		
		@Override
		public Object getCellEditorValue()
		{
			return combo.getSelectedIndex();
		}

		@Override
		public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
		{
			Integer i = (Integer)value;
			combo.setSelectedIndex(i);
			
			return combo;
		}
		
	}
	
	static class CustomIntegerCellRenderer implements TableCellRenderer
	{
		private JComboBox<String> combo = new JComboBox<String>();
		
		public CustomIntegerCellRenderer(String[] values)
		{
			for(String value : values)
				this.combo.addItem(value);
		}
		
		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
		{
			Integer i = (Integer)value;
			combo.setSelectedIndex(i);
			return combo;
		}
	}
	
	
	
	public static void main(String[] args)
	{
		String[] columnNames = {"", ""};
		Object[][] data =
			 {
			 { "A", ""},
			 { "B", ""},
			 { "C", new Integer(0) },
			 { "D", new Boolean(false) },
			 { "E", "A.B.C" },
			 { "F", new Integer(1) }
			 };
		
		JTable table = new JTable(data, columnNames) {
			
			private static final long serialVersionUID = -740223646625258374L;
			
			@Override
			public boolean isCellEditable(int rowIndex, int columnIndex)
			{
				if(columnIndex == 1)
					return true;
				else
					return false;
			}
			
			@Override
			public TableCellEditor getCellEditor(int row, int column)
			{
		        TableColumn tableColumn = getColumnModel().getColumn(column);
		        TableCellEditor editor = tableColumn.getCellEditor();
		        if(editor == null)
		        {
		            editor = getDefaultEditor(getValueAt(row, column).getClass());
		        }
		        
		        return editor;
		    }
			
			@Override
			public TableCellRenderer getCellRenderer(int row, int column)
			{
		        TableColumn tableColumn = getColumnModel().getColumn(column);
		        TableCellRenderer renderer = tableColumn.getCellRenderer();
		        if(renderer == null)
		        {
		            renderer = getDefaultRenderer(getValueAt(row, column).getClass());
		        }
		        
		        return renderer;
		    }
		};
		
		
		
		String values[] = new String[]{"m", "f"};
			
		table.setDefaultRenderer(Integer.class, new CustomIntegerCellRenderer(values));
		table.setDefaultEditor(Integer.class, new CustomIntegerCellEditor(values));
		
		
		final JFrame f = new JFrame("Ein Frame zum Schließen");
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		f.add(table, BorderLayout.CENTER);
		
		f.pack();
		f.setVisible(true);
	}
	
}
```

Das Hauptproblem ist meines Erachtens, dass das TableModel (wenn keines angegeben) für alle Columns immer Object.class zurückgibt. Dafür sorgt die getColumnClass(int column) Methode. Das wird dann alles in JTable von getCellRenderer(int row, int column) aufgerufen (bzw getCellEditor).

Ich habe einfach in getCellRenderer() die Zeile:

```
renderer = getDefaultRenderer(getColumnClass(column));
```

gegen


```
renderer = getDefaultRenderer(getValueAt(row, column).getClass());
```

getauscht. Wie du siehst habe ich lediglich für die Integer.class einen neuen Renderer/Editor geschrieben. Die Standard Editor/Renderer für String bzw. Boolean sind schon so wie du haben möchtest.


----------



## Developer_X (17. Nov 2014)

Hey, danke für deine Hilfe.
Ich muss nur ehrlich sagen, das ganze ist so umständlich dass ich mich dazu beschlossen habe,
lieber ein GridLayout zu verwenden, weil das so viel zu umständlich wird, besonders, wenn ich die 
Werte dann wieder auslesen will.

Im Grund will ich ja eine Art Formular gestalten, doch so ist es am Einfachsten.

Danke für deine Hilfe,
m.f.G. Developer_X


----------

