2013-02-26 10 views
5

Ho letto la maggior parte delle risposte di JTable/JComboBox ad altre domande di questo tipo, ma non ho ancora trovato una soluzione al mio problema.JComboBox non riesce ad espandersi in JTable TableHeader

Ho creato una tabella con elementi TableHeader JComboBox. Nessuno degli elementi di JComboBox si aprirà per visualizzare un elenco di elementi. Come posso visualizzare gli elenchi articoli per i singoli elementi di JComboBox?

Si noti che un elemento distintivo di questa domanda è che JComboBox si trova in TableHeader, non incorporato in una cella JTable.

Qualsiasi aiuto è apprezzato.

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 per includere uno SSCCE, senza dover essere chiesto prima. – mre

+0

non correlato: a) [non utilizzare setXXSize] (http://stackoverflow.com/a/7229519/203657) b) non estendere JSomething se è possibile raggiungere lo stesso obiettivo usandolo c) setSize ha o nessun effetto o stai facendo qualcosa di fondamentalmente sbagliato (non usando un LayoutManager) – kleopatra

+1

@kleopatra - Preferisco la composizione sull'ereditarietà come suggerisci tu. Stavo usando questo come banco di prova per scoprire cosa impediva il JComboBox di aprirsi, quindi niente LayoutManager. Sto solo cercando di mantenere Simple in SSCCE. – Todd

risposta

4

Questo effettivamente funziona esattamente come previsto. Penso che l'indizio sia TableCellRenderer.

I programmi di rendering sono in genere componenti non interattivi. Di solito sono solo una "istantanea" del componente dipinto su una superficie e non c'è in genere modo per un utente di interagire con loro.

Questo è il comportamento previsto.

Al fine di fornire funzionalità modificabile per l'intestazione della tabella, si sta andando ad avere bisogno di fornire l'implementazione di un JTableHeader

Date un'occhiata a questo example per alcune idee

+0

Vedere anche questo [D & R] (http://stackoverflow.com/q/7137786/230513). – trashgod

+0

@MadProgrammer - grazie per aver chiarito questo per me. Pensavo che un renderer avrebbe reso una componente completamente funzionale, non solo i suoi aspetti visivi. – Todd

+0

@trashgod - Avevo esaminato quell'elemento prima della pubblicazione, ma l'ho interpretato per fornire una soluzione basata sulle celle della tabella, non sull'intestazione, sebbene l'argomento originale riguardasse l'intestazione. Vedo che non ero corretto. Grazie. – Todd

0

Here è un esempio che utilizza un JComboBox in un TableTable JTable.

Per altri tipi di componenti è più semplice, date un'occhiata here.

enter image description here