Как да сортирате низове от JComboBoxes в JTables?

Имам следния проблем:

Вмъкнах в 5-та колона на моята JTable за всеки ред JComboBox-Object. Всичко е наред, докато не искам да сортирам редове в колоната с setAutoCreateRowSorter(true). В този случай получавам следното изключение:

ClassCastException: java.lang.String cannot be cast to javax.swing.JComboBox

Ето моите класове, които използвам за моята JTable:

Моделът на таблицата:

private class MyTableModel implements TableModel {

        @Override
        public void addTableModelListener(TableModelListener l) {
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {

            switch (columnIndex) {
            case 0:
                return String.class;
            case 1:
                return String.class;
            case 2:
                return String.class;
            case 3:
                return Number.class;
            case 4:
                return Boolean.class;
            case 5:
                return JComboBox.class;  // modifyed!

            default:
                return null;
            }

        }

        @Override
        public int getColumnCount() {
            return columnNames.length;
        }

        @Override
        public String getColumnName(int columnIndex) {
            return columnNames[columnIndex];
        }

        @Override
        public int getRowCount() {
            return data[0].length - 1;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            return data[rowIndex][columnIndex];

        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            switch (columnIndex) {
            case 5:
                return true;
            default:
                return false;
            }

        }

        @Override
        public void removeTableModelListener(TableModelListener l) {
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            data[rowIndex][columnIndex] = aValue;

        }

    }

TableCellRenderer:

public class StringTableCellRenderer extends JLabel implements
        TableCellRenderer {

    private static final long serialVersionUID = 1L;

    public StringTableCellRenderer() {
        setOpaque(true);
        setLayout(new BorderLayout());
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        Font font = getFont().deriveFont(Font.BOLD, 15);

        if ((row % 2) == 0) {
            setBackground(new Color(240, 255, 255));
        } else {
            setBackground(new Color(191, 239, 255));
        }

        if (isSelected) {
            setBackground(new Color(0, 191, 255));
        }

        setHorizontalAlignment(JLabel.CENTER);
        setForeground(Color.BLACK);
        setFont(font);

        if (value instanceof JComboBox) {
            System.out.println("Renderer: "+column+" "+row+" "+((JComboBox<?>)value).getSelectedIndex());

            setText((String) ((JComboBox<?>) value).getSelectedItem());
        } else {
            setText(value.toString());
        }

        return this;
    }

}

TableCellEditor:

  public class MyTableCellEditor extends AbstractCellEditor implements
        TableCellEditor, ActionListener {

    private static final long serialVersionUID = 1L;
    private JComboBox<?>[] comboList = new JComboBox<?>[5];
    private int column = 0;

    @SuppressWarnings("unchecked")
    public MyTableCellEditor() {

        for (int i = 0; i < comboList.length; i++) {
            comboList[i] = new JComboBox<String>();
            setComboBox((JComboBox<String>) comboList[i]);
            comboList[i].setName("ComboBox_" + i);
        }

    }

    public void setComboBox(JComboBox<String> comboBox) {
        comboBox.addItem("Me");
        comboBox.addItem("You");
        comboBox.addItem("They");
        comboBox.addItem("Us");
        comboBox.addItem("We");
    }

    @Override
    public void actionPerformed(ActionEvent event) {
    }

    @Override
    public Object getCellEditorValue() {
        System.out.println("Editor: getCellEditorValue() "+comboList[column].getSelectedIndex());
        if (comboList[column].getSelectedIndex()==-1) {
            return (String) comboList[column].getItemAt(0);
        } else {
            return (String) comboList[column].getSelectedItem(); // returns String not JCombobox!
        }
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value,
            boolean isSelected, int row, int column) {

        String fieldValue = null;
        System.out.println("Editor: getTableCellEditorComponent");
        if (value instanceof JComboBox<?>) {
            fieldValue = (String) ((JComboBox<?>) value).getSelectedItem();
        }
        this.column = column - 1;
        comboList[column - 1].setSelectedItem(fieldValue);

        return comboList[column - 1]; // for each row of column 5 an own JComboBox object

    }

}

Реших проблема сам:

В TableModel getColumnClass()-методът за колона 5 връща JCombobox.class-обект.

В TableCellEditor за всеки ред в 5-та колона има собствен JComboBox-Object и getCellEditorValue()-методът връща getSelectedItem() на съответния JComboBox-Object.

Така че Jtable наистина има JComboBox-обект (getValueAt()-метод за колона 5 от TableModel и getTableCellEditorComponent()-метод от TableCellEditor), но върнатата стойност въпреки това е низ (getCellEditorValue() от TableCellEditor и getTableCellRendererComponent()-метод от TableCellRenderer).

Надявам се това да помогне на всеки с подобни проблеми...


person user3133542    schedule 28.02.2015    source източник


Отговори (1)


Защо създавате персонализиран Comparator? Данните в TableModel са String данни, а не JCombobox. RowSorter на таблицата вече знае как да сортира String данни.

Всъщност НИКОГА не трябва да съхранявате JComboBox в TableModel. Ако наистина правите това, тогава се отървете от него.

След това се отървете от вашия персонализиран Comparator и той трябва да работи добре.

Ако се опитвате да използвате различни стойности за комбинираното поле в различни редове, тогава трябва да опитате нещо като: как да добавя различни редактори на клетки за една колона в JTable?

person camickr    schedule 28.02.2015
comment
защо никога не трябва да съхранявам JComboBox в моята Jtable? - person user3133542; 01.03.2015
comment
Това не е начинът, по който една маса работи. Вие съхранявате данни в TableModel и JTable ще изобрази данните с помощта на подходящо средство за изобразяване и ще редактира данните с помощта на подходящ редактор. - person camickr; 01.03.2015