1

I got a (more or less) empty JTable in my GUI without any JCheckBoxes in the beginning. After a button is pressed I want to fill the table with names (Strings) and JCheckBoxes depending on the content of an array. The part with the names already works fine but I'm not able to change the class of single cells to boolean, instead a true or false appears in the JTable where the JCheckBox actually should be. I know that you can fill a complete column with JCheckBoxes if you set the column type to boolean in the beginning.

My question now is if it is possible to change the column typ of a single cell.

This is the code where the JTable is created:

    table = new JTable();
    table.setRowMargin(3);
    table.setRowHeight(25);
    table.setFillsViewportHeight(true);
    table.setModel(new DefaultTableModel(
            new Object[][] {
                {null, "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"},
                {"", "2016-02-29", "2016-03-01", "2016-03-02", "2016-03-03", "2016-03-04"},
                {" 1. Lesson", null, null, null, null, null},
                {" 2. Lesson", null, null, null, null, null},
                {" 3. Lesson", null, null, null, null, null},
                {" 4. Lesson", null, null, null, null, null},
                {" 5. Lesson", null, null, null, null, null},
                {" 6. Lesson", null, null, null, null, null},
                {" 7. Lesson", null, null, null, null, null},
                {" 8. Lesson", null, null, null, null, null},
                {" 9. Lesson", null, null, null, null, null},
                {" 10. Lesson", null, null, null, null, null},
            },
            new String[] { "Empty", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" }
        ) 
        {
            Class[] columnTypes = new Class[] 
                {
                    String.class, Object.class, Object.class, Object.class, Object.class, Object.class
                };
            public Class getColumnClass(int columnIndex) 
            {
                return columnTypes[columnIndex];
            }
        });
    table.setBorder(new LineBorder(new Color(0, 0, 0)));
    table.setBounds(381, 11, 518, 300);
    panel.add(table);

This is the part where the content of the JTable is changed:

public void tableUpdate(Object[][] a)
{
    for(int row = 0; row < 11; row++)
    {
        for(int column = 0 ; column < 5; column++)
        {
            table.setValueAt(a[column][row], row+1, column+1);

        }
    }
}

If you need further information please ask me and many thanks in advance.

jonas001
  • 11
  • 3
  • 2
    Return `Boolean.class` from `getColumnClass` for the columns you want to appear as checkboxes – MadProgrammer Mar 05 '16 at 22:30
  • 1
    the problem is that I don't want a whole column only with checkboxes, I want both, names (strings) and checkboxes, depending on the content of the array – jonas001 Mar 05 '16 at 22:33
  • 1
    Okay, that's not really how JTable works. A column is only suppose to have a single type of data – MadProgrammer Mar 05 '16 at 22:39
  • hmm okay, do you know a solution for this problem where I don't have to create 72 labels and 50 checkboxes? – jonas001 Mar 05 '16 at 22:45
  • I guess it would depend on why you need two different values in a single column. It can be done but it's complicated – MadProgrammer Mar 05 '16 at 22:59

1 Answers1

1

You could do something like this:

import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

public class TablePropertyEditor extends JFrame
{
    public TablePropertyEditor()
    {
        String[] columnNames = {"Type", "Value"};
        Object[][] data =
        {
            {"String", "I'm a string"},
            {"Date", new Date()},
            {"Integer", new Integer(123)},
            {"Double", new Double(123.45)},
            {"Boolean", Boolean.TRUE}
        };

        JTable table = new JTable(data, columnNames)
        {
            private Class editingClass;

            public TableCellRenderer getCellRenderer(int row, int column)
            {
                editingClass = null;
                int modelColumn = convertColumnIndexToModel(column);

                if (modelColumn == 1)
                {
                    Class rowClass = getModel().getValueAt(row, modelColumn).getClass();
                    return getDefaultRenderer( rowClass );
                }
                else
                    return super.getCellRenderer(row, column);
            }

            public TableCellEditor getCellEditor(int row, int column)
            {
                editingClass = null;
                int modelColumn = convertColumnIndexToModel(column);

                if (modelColumn == 1)
                {
                    editingClass = getModel().getValueAt(row, modelColumn).getClass();
                    return getDefaultEditor( editingClass );
                }
                else
                    return super.getCellEditor(row, column);
            }

            //  This method is also invoked by the editor when the value in the editor
            //  component is saved in the TableModel. The class was saved when the
            //  editor was invoked so the proper class can be created.

            public Class getColumnClass(int column)
            {
                return editingClass != null ? editingClass : super.getColumnClass(column);
            }
        };

        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane( table );
        getContentPane().add( scrollPane );
    }

    public static void main(String[] args)
    {
        TablePropertyEditor frame = new TablePropertyEditor();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}

It determines the renderer/editor to be used based on the data in the cell not the column class.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • `getModel().getValueAt(row` << using view index to index the model. Since `getCellRenderer` will only be called for cells that are visible in the view, you might as well use `this.getValueAt(row,column)`. – TT. Mar 06 '16 at 07:49
  • @TT., actually I wasn't worried about the row. I was just trying to stress that for rendering/editing purposes the class of the "model column" was the relevant class to use. Because I use the model column in the if condition I wanted to be consistent and get the data from the specific column in the model as well. – camickr Mar 06 '16 at 19:30