5

I have read through the majority of the JTable/JComboBox responses to other questions of this ilk, but haven't yet found a solution to my problem.

I have created a table that has JComboBox TableHeader elements. None of the JComboBox elements will open to display a list of items. How do I get the item lists for the individual JComboBox elements to display?

Please note that a distinguishing element of this question is that the JComboBox is in the TableHeader, not embedded within a JTable cell.

Any help is appreciated.

SSCE

import java.awt.Component;
import java.awt.Dimension;
import java.util.Enumeration;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

public class ComboHeaderTest extends JScrollPane {

private static final Dimension DEFAULT_SIZE = new Dimension(200, 200);

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            new ComboHeaderTest().initComponents();
        }
    });
}

private ComboHeaderTest() {

    final String[][] data = { {"Header 1", "Header 2", "Header 3"},
                                {"A", "B", "C"},
                                {"D", "E", "F"},
                                {"G", "H", "I"}};

    setViewportView(getTable(data));
    setPreferredSize(DEFAULT_SIZE);
}

private void initComponents() {

    JFrame frame = new JFrame("ComboHeaderTest");
    frame.add(this);
    frame.pack();
    frame.setVisible(true);
}

private JTable getTable(final String[][] data) {
    final String[] items = data[0];

    final ComboHeaderRenderer[] columnHeaders = new ComboHeaderRenderer[items.length];
    for(int i = 0; items.length > i; ++i) {
        columnHeaders[i] = new ComboHeaderRenderer(items);
    }

    final JTable table = new JTable(data, columnHeaders);

    final Enumeration<TableColumn> tableEnum = table.getColumnModel().getColumns();
    for (int columnIndex = 0; tableEnum.hasMoreElements(); ++columnIndex) {
        final TableColumn column = tableEnum.nextElement();

        final ComboHeaderRenderer combo = columnHeaders[columnIndex];
        column.setHeaderValue(combo.getItemAt(columnIndex));
        column.setHeaderRenderer(combo);
    }

    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    table.setRowSelectionAllowed(true);
    table.setColumnSelectionAllowed(false);
    table.setCellSelectionEnabled(false);
    table.setFillsViewportHeight(true);

    table.setSize(DEFAULT_SIZE);
    table.validate();

    return table;
}

private static class ComboHeaderRenderer extends JComboBox implements TableCellRenderer{
    public ComboHeaderRenderer(final String[] entries) {
        for (int i = 0; entries.length > i; ++i) {
            addItem(entries[i]);
        }
    }

    @Override
    public Component getTableCellRendererComponent(final JTable table, final Object value,
            final boolean isSelected, final boolean hasFocus, final int row, final int column) {
        setSelectedItem(value);
        return this;
    }
}
}
Todd
  • 1,895
  • 4
  • 15
  • 18
  • +1 for including an SSCCE without having to be asked first. – mre Feb 26 '13 at 20:57
  • unrelated: a) [don't use setXXSize](http://stackoverflow.com/a/7229519/203657) b) don't extend a JSomething if you can reach the same goal by using it c) setSize has either no effect or you are doing something fundamentally wrong (by not using a LayoutManager) – kleopatra Feb 27 '13 at 08:23
  • 1
    @kleopatra - I prefer composition over inheritance as you suggest. I was using this as a test bed to discover what was preventing the JComboBox from unfolding, so no LayoutManager. Just trying to keep the Simple in SSCCE. – Todd Feb 27 '13 at 19:51

2 Answers2

4

This actually works exactly as expected. I think the clue is TableCellRenderer.

Renderer's are typically non-interactive components. They are usually just a "snap-shot" of the component painted on to a surface and there is typically no way for a user to interact with them.

This is the expected behavior.

In order to supply editable functionality to the table header, you're going to need to supply your implementation of a JTableHeader

Have a look at this example for some ideas

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • @MadProgrammer - thanks for clarifying that for me. I thought a renderer would render a completely functional component, not just its visual aspects. – Todd Feb 27 '13 at 19:43
  • @trashgod - I had looked at that item prior to posting, but I interpreted it to provide a solution based upon the table cells, not the header, though the original topic was about the header. I see now that I was incorrect. Thanks. – Todd Feb 27 '13 at 19:47
0

Here is an example that uses a JComboBox in a JTable TableHeader.

For other types of components is easier, have a look here.

enter image description here

Community
  • 1
  • 1
luca
  • 7,178
  • 7
  • 41
  • 55