Как сделать так, чтобы в столбце JTable можно было выбрать только один флажок

Я использую DefaultTableModel следующим образом:

  DefaultTableModel model = new DefaultTableModel (COLUMNS, 0 )
  {
      @Override
      public boolean isCellEditable(int row, int column)
      {
          return (getColumnName(column).equals("Selected"));
      }

      public Class getColumnClass(int columnIndex)
      {
          if(getColumnName(columnIndex).equals("Selected"))
              return Boolean.class;
          return super.getColumnClass(columnIndex);
      }     
  };

Теперь я хочу, чтобы в столбце «Выбрано» можно было выбрать только один флажок. Как это может быть сделано. Я также пробовал следующий метод, но он не работает.

 public void fireTableCellUpdated(int row,int column)
 {
     if(getColumnName(column).equals("Selected"))
     {
         for(int i = 0; i<getRowCount() && i!=row;i++)
            setValueAt(Boolean.FALSE, row, column);
     }
 }

person eatSleepCode    schedule 30.07.2013    source источник
comment
Если я вас правильно понял, вы хотите реализовать функциональность переключателя?   -  person Michał Tabor    schedule 30.07.2013
comment
не работает - можно поконкретнее? Выдает ли он Exception или другую полезную информацию? Что ты видишь?   -  person mthmulders    schedule 30.07.2013
comment
Могу ли я узнать, какую IDE вы используете?   -  person Nitesh Verma    schedule 30.07.2013
comment
Выдает исключение StackOverFlow.   -  person eatSleepCode    schedule 30.07.2013
comment
@NiteshVerma Я использую JDeveloper, но есть ли разница?   -  person eatSleepCode    schedule 30.07.2013
comment
Нет, нет, совсем нет. Просто собираю больше фактов об этом.   -  person Nitesh Verma    schedule 30.07.2013
comment
Вы получаете StackOverFlowException, потому что setValueAt() приведет к вызову fireTableCellUpdated(), который снова вызывает первый.   -  person kiheru    schedule 30.07.2013
comment
Вероятно, он вызывает StackOverflow, потому что ваш механизм fireTableCellUpdated бесконечно каскадируется.   -  person Jannis Alexakis    schedule 30.07.2013
comment
Возможно, он хотел, чтобы вы спросили Stack Overflow.   -  person tbodt    schedule 30.07.2013
comment
Есть ли другой метод решения этой проблемы?   -  person eatSleepCode    schedule 30.07.2013
comment
пожалуйста, для чего нужна одна колонка??? или ряд??? который содержит JCheckBox,   -  person mKorbel    schedule 30.07.2013
comment
для лучшей помощи сонер публикует SSCCE, короткий, исполняемый, компилируемый, только о JFrame, JTable и с жестким значением для TableModel   -  person mKorbel    schedule 30.07.2013
comment
@mKorbel У меня есть JTable с одним столбцом как boolean.class, в таблице может быть много строк, но я хочу выбрать только один флажок среди всех строк.   -  person eatSleepCode    schedule 30.07.2013
comment
@eatSleepCode 1. У меня есть JTable с одним столбцом как boolean.class ---› понятия не имею из опубликованного кода, почему ад в этом мире требуется для вызова fireWhatever для DeafultTableModel, не делайте этого, подготовьтесь (ищите здесь для) SSCCE, 2. но я хочу сделать только один флажок, выбранный среди всех строк ---> ничего особенного для JTable на основе DefaultTableModel, все собирается правильно переопределить setValueAt, и блокируя, избегая (каскадного) бесконечного цикла (на основе комментариев здесь),   -  person mKorbel    schedule 30.07.2013
comment
Некоторые альтернативы приведены здесь.   -  person trashgod    schedule 30.07.2013
comment
@mKorbel, не могли бы вы привести пример кода для реализации метода setValueAt.   -  person eatSleepCode    schedule 30.07.2013


Ответы (3)


  • @eatSleepCode написал @mKorbel, не могли бы вы привести пример кода для реализации метода setValueAt.

  • код для (используется OP) DefaultTableModel,

  • для кода на основе AbstractTableModel требуется держать порядок кода для нотификатора fireTableCellUpdated(rowIndex, columnIndex);, т.к/иначе ничего не будет перерисовываться в JTables view,

  • есть несколько важных различий между этими двумя моделями и их уведомителями, и (на мой взгляд) нет причин беспокоиться и использовать AbstractTableModel для основных вещей (99% моделей таблиц)

введите здесь описание изображения. . . . введите здесь описание изображения. . . . введите здесь описание изображения

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;

public class TableRolloverDemo {

    private JFrame frame = new JFrame("TableRolloverDemo");
    private JTable table = new JTable();
    private String[] columnNames = new String[]{"Column"};
    private Object[][] data = new Object[][]{{false}, {false}, {true}, {true},
        {false}, {false}, {true}, {true}, {false}, {false}, {true}, {true}};

    public TableRolloverDemo() {
        final DefaultTableModel model = new DefaultTableModel(data, columnNames) {
            private boolean ImInLoop = false;

            @Override
            public Class<?> getColumnClass(int columnIndex) {
                return Boolean.class;
            }

            @Override
            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return true;
            }

            @Override
            public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
                if (columnIndex == 0) {
                    if (!ImInLoop) {
                        ImInLoop = true;
                        Boolean bol = (Boolean) aValue;
                        super.setValueAt(aValue, rowIndex, columnIndex);
                        for (int i = 0; i < this.getRowCount(); i++) {
                            if (i != rowIndex) {
                                super.setValueAt(!bol, i, columnIndex);
                            }
                        }
                        ImInLoop = false;
                    }
                } else {
                    super.setValueAt(aValue, rowIndex, columnIndex);
                }
            }
        };
        table.setModel(model);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JScrollPane(table));
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }


    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                TableRolloverDemo tableRolloverDemo = new TableRolloverDemo();
            }
        });
    }
}
person mKorbel    schedule 30.07.2013
comment
нежное напоминание (уже в который раз) - код ответа должен быть таким же SSCCE, как и код вопроса :-) Эффекты ролловера хороши, но не имеют отношения к вопросу. - person kleopatra; 30.07.2013

Вы получаете исключение переполнения стека, потому что метод setValueAt() снова и снова запускает метод fireTableCellUpdated().

Вместо этого попробуйте использовать прослушиватель таблицы, который будет прослушивать изменение значения флажка и установит для всех остальных флажков значение false.

person Michał Tabor    schedule 30.07.2013
comment
Не будет ли это иметь точно такой же эффект? - person Jannis Alexakis; 30.07.2013

Вы можете создать свой собственный редактор ячеек, который объединяет все флажки в столбце в ButtonGroup. вот как:

public class VeryComplicatedCellEditor extends DefaultCellEditor {
    private ArrayList<ButtonGroup> groups;

    public getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        JCheckBox checkBox = new JCheckBox();
        growToSize(column);
        groups.get(column).add(checkBox);
        return checkBox;
    }

    private growToSize(int size) {
        groups.ensureCapacity(size);
        while (groups.size() < size)
            groups.add(new ButtonGroup());
    }
}

Есть некоторые сложности, возникающие из-за того, что мы не знаем, насколько велика таблица, о которых в основном заботится метод growToSize.

Это работает путем ведения списка ButtonGroup, по одному для каждого столбца. Компонент редактора для каждой ячейки добавляется в группу кнопок для ее столбца.

person tbodt    schedule 30.07.2013
comment
Это интересно. Это выполнимо? Есть примеры? - person Jannis Alexakis; 30.07.2013
comment
просто неправильно а) не соответствует своему контракту: должен уведомлять слушателей, когда редактирование прекращается б) создание нового флажка (и группы кнопок) при каждом вызове - как это должно решить проблему? c) не настраивая флажок - person kleopatra; 30.07.2013