JTable,每行有不同的JComboBox-es

时间:2014-03-24 09:13:01

标签: java swing jtable jcombobox

我创建了JTable,其中包含有关员工的信息。在这个JTable中,我添加了名为" Qualifications"的列。此列由JComboBox表示(每行的内容不同)。例如:

Row 1 |  JComboBox(){"Programmer","Web"}
Row 2 |  JComboBox(){"Writer","Editor"}

JComboBox内容取自List<String> employees[row].getQualification()

问题在于第1行和第2行中的所选项目是&#34;程序员&#34;然而&#34;程序员&#34;不应出现在第2行中。只有当我点击JComboBox时,才会显示正确的列表,即第2行 - {&#34; Writer&#34;,&#34;编辑&#34;}。

    TableColumn column = table.getColumnModel().getColumn(5);
    column.setCellRenderer(getRenderer());

    private TableCellRenderer getRenderer() {
    return new TableCellRenderer() {

        private JComboBox<String> box = new JComboBox<String>();
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column) {            
            for (String q : employees[row].getQualification())
                box.addItem(q);
            box.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
            box.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());
            return box;
           }
        };
    }

3 个答案:

答案 0 :(得分:5)

覆盖getCellEditor()的{​​{1}}方法。类似的东西:

JTable

答案 1 :(得分:3)

  

JComboBox-es只出现在点击

因为您将它们用作CellEditor,只有在编辑单元格时才会使用它们。如果您希望每次都将JComboBox列显示为单元格,则需要使用TableCellRendererread about that。以下是JComboBox作为渲染器的简单示例:

import java.awt.Component;

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

public class TestFrame extends JFrame{

    public TestFrame(){
        init();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setVisible(true);
    }

    private void init() {
        JTable t = new JTable(3,3);
        TableColumn column = t.getColumnModel().getColumn(2);
        column.setCellRenderer(getRenderer());
        add(new JScrollPane(t));
    }

    private TableCellRenderer getRenderer() {
        return new TableCellRenderer() {

            private JComboBox<String> box = new JComboBox<String>(new String[]{"1","2"});
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value,
                    boolean isSelected, boolean hasFocus, int row, int column) {
                box.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
                box.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());
                return box;
            }
        };
    }

    public static void main(String... s){
        new TestFrame();
    }

}

enter image description here

答案 2 :(得分:0)

由于@ alex2410,我清理了代码并将其包装到ComboTable类中,该类应该为您完成工作。用每个行值的哈希表实例化ComboTable类(演示假定2列,但您可以添加更多列)。注意MyMap.of只是Java 9 Map.of的包装,因为那时我正在使用Java 8。与MyList.of

相同
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.EventObject;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

import rs.code.utils.MyList;
import rs.code.utils.MyMap;

public class Test extends JFrame
{
    private static final long serialVersionUID = 1L;
    public ComboTable table = new ComboTable(MyMap.of("Gender", MyList.of("male", "female"), "City", MyList.of("london", "bedord"), "orientation", MyList.of("left", "right")));
    public Test()
    {
        super("EachRow Editor Example");
        JScrollPane scroll = new JScrollPane(table);
        getContentPane().add(scroll, BorderLayout.CENTER);
        setPreferredSize(new Dimension(400, 120));
        setLocation(150, 100);
        pack();
        setVisible(true);

    }

    public static void main(String[] args)
    {
        Test frame = new Test();
        frame.addWindowListener(new WindowAdapter()
        {
            @Override
            public void windowClosing(WindowEvent e)
            {
                System.out.println(frame.table.getSelectedValues().toString());
                System.exit(0);
            }
        });
    }
}

class ComboTable extends JTable
{
    private static final long serialVersionUID = 1L;
    protected Map<Integer, ComboCellEditor> editors = new LinkedHashMap<>();

    public ComboTable(Map<String, List<String>> rows)
    {
        setModel(new DefaultTableModel(new String[] {"Attribute", "Value"}, rows.size()));
        setRowHeight(20);
        EachRowEditor rowEditor = new EachRowEditor(this);
        int i = 0;
        for(String key : rows.keySet())
        {
            getModel().setValueAt(key, i, 0);
            editors.put(i++, new ComboCellEditor(createComboBox(rows.get(key))));
        }

        getColumn("Value").setCellEditor(rowEditor);
        getColumn("Value").setCellRenderer(getRenderer());
    }

    public Map<Integer, ComboCellEditor> getEditors()
    {
        return editors;
    }

    public Map<String, String> getSelectedValues()
    {
        Map<String, String> values = new LinkedHashMap<>();
        for(int i=0;i<getModel().getRowCount();i++)
        {
            values.put(getModel().getValueAt(i, 0).toString(), editors.get(i).getComboBox().getSelectedItem().toString());
        }
        return values;
    }

    private JComboBox<String> createComboBox(List<String> elements)
    {
        JComboBox<String> comboBox = new JComboBox<>();
        for (String element : elements)
        {
            comboBox.addItem(element);
        }
        comboBox.setSelectedIndex(0);
        comboBox.addComponentListener(new ComponentAdapter()
        {
            @Override
            public void componentShown(ComponentEvent e)
            {
                final JComponent c = (JComponent) e.getSource();
                SwingUtilities.invokeLater(new Runnable()
                {
                    @SuppressWarnings("rawtypes")
                    @Override
                    public void run()
                    {
                        c.requestFocus();
                        System.out.println(c);
                        if (c instanceof JComboBox)
                        {
                            System.out.println(((JComboBox) c).getSelectedItem());
                        }
                    }
                });
            }
        });

        return comboBox;
    }

    private TableCellRenderer getRenderer()
    {
        return new TableCellRenderer()
        {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
            {
                editors.get(row).getComboBox().setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
                editors.get(row).getComboBox().setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());
                return editors.get(row).getComboBox();
            }
        };
    }
}

class ComboCellEditor extends DefaultCellEditor
{
    private static final long serialVersionUID = 1L;
    private final JComboBox<String> comboBox;

    public ComboCellEditor(JComboBox<String> comboBox)
    {
        super(comboBox);
        this.comboBox = comboBox;
    }

    public JComboBox<String> getComboBox()
    {
        return comboBox;
    }
}

class EachRowEditor implements TableCellEditor
{
    private TableCellEditor editor;
    private final TableCellEditor defaultEditor;
    private final ComboTable table;

    public EachRowEditor(ComboTable table)
    {
        this.table = table;
        defaultEditor = new DefaultCellEditor(new JTextField());

    }

    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
    {
        return editor.getTableCellEditorComponent(table, value, isSelected, row, column);
    }

    public Object getCellEditorValue()
    {
        return editor.getCellEditorValue();
    }

    public boolean stopCellEditing()
    {
        return editor.stopCellEditing();
    }

    public void cancelCellEditing()
    {
        editor.cancelCellEditing();
    }

    public boolean isCellEditable(EventObject anEvent)
    {
        selectEditor((MouseEvent) anEvent);
        return editor.isCellEditable(anEvent);
    }

    public void addCellEditorListener(CellEditorListener l)
    {
        editor.addCellEditorListener(l);
    }

    public void removeCellEditorListener(CellEditorListener l)
    {
        editor.removeCellEditorListener(l);
    }

    public boolean shouldSelectCell(EventObject anEvent)
    {
        selectEditor((MouseEvent) anEvent);
        return editor.shouldSelectCell(anEvent);
    }

    protected void selectEditor(MouseEvent e)
    {
        int row;
        if (e == null)
        {
            row = table.getSelectionModel().getAnchorSelectionIndex();
        }
        else
        {
            row = table.rowAtPoint(e.getPoint());
        }
        editor = table.getEditors().get(row);
        if (editor == null)
        {
            editor = defaultEditor;
        }
    }
}