2013-02-26 68 views
5

我已阅读了大部分JTable/JComboBox对此类问题的其他问题的回复,但尚未找到解决问题的方法。JComboBox无法在JTable TableHeader中展开

我创建了一个具有JComboBox TableHeader元素的表。 JComboBox元素都不会打开以显示项目列表。如何获取单个JComboBox元素的项目列表以显示?

请注意,此问题的一个显着元素是JComboBox位于TableHeader中,而不是嵌入JTable单元格中。

任何帮助表示赞赏。

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; 
    } 
} 
} 
+0

+1用于包括SSCCE而不必先询问。 – mre 2013-02-26 20:57:05

+0

无关:a)[不要使用setXXSize](http://stackoverflow.com/a/7229519/203657)b)如果使用它可以达到相同的目标,则不要扩展JSomething c)setSize具有没有效果,或者你正在做一些根本性错误的事情(不使用LayoutManager) – kleopatra 2013-02-27 08:23:54

+1

@kleopatra - 我建议你比继承更喜欢构图。我将它用作测试平台,以发现阻止JComboBox展开的因素,因此没有LayoutManager。只是想在SSCCE中保持简单。 – Todd 2013-02-27 19:51:40

回答

4

这实际上工程完全按照预期。我认为线索是TableCellRenderer

渲染器通常是非交互式组件。它们通常只是绘制在表面上的组件的“快照”,用户通常无法与它们进行交互。

这是预期的行为。

为了提供编辑功能表头,你将需要提供你的JTableHeader

实施看一看这个example的一些想法

+0

另请参阅此[问与答](http://stackoverflow.com/q/7137786/230513)。 – trashgod 2013-02-27 02:35:30

+0

@MadProgrammer - 感谢为我澄清这一点。我认为渲染器会渲染一个完整的功能组件,而不仅仅是其视觉方面。 – Todd 2013-02-27 19:43:16

+0

@trashgod - 我在发布之前已经查看过这个项目,但我解释它是基于表格单元格提供解决方案,而不是标题,尽管原始主题是关于标题的。我现在看到我错了。谢谢。 – Todd 2013-02-27 19:47:45

0

Here是一个例子在JTable TableHeader中使用JComboBox。

对于其他类型的组件更容易,看看here

enter image description here