Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: GUI и Java FX приложения > JTable - попытка убрать недовведенный ряд


Автор: _Y_ 31.12.2010, 14:32
Обнаружил вот такой "феномен". Имеем табцицу JTable и две кнопки. Одна кнопка добавляет ряд к таблице, другая убирает все пустые ряды. Теперь делаем так (вариант А):
  • Запускаем программу
  • Добавляем кнопкой в таблицу несколько рядов.
  • Кликаем на какой-нибудь ячейке не первого ряда и начинаем вводить текст.
  • Не закончив ввод текста (т.е. при активном cellEditor), кликаем кнопку убирающую пустые ряды. Ряд с незаконченным вводом не убирается, а "зависает в воздухе".
  • Кликаем куда-нибудь в освободившееся поле. Получаем ошибку "ArrayIndexOutOfBoundsException"
Теперь вариант В:
  • Запускаем программу и делаем все то же самое, но после удаления рядов нигде не кликаем - просто любуемся на странно зависшую величину.
  • Кликаем нексколько раз на кнопке, добавляющей ряды. "Висящее в воздухе" значение оказывается на своем законном месте в таблице.
Вариант С: таблица помещена не на форму а в JScrollPane
  • Запускаем программу и делаем все то же самое. Значение в воздухе не повисает. Таблица остается пустой (если, конечно, в ней других данных не было).
  • Кликаем где угодно - никаких ошибок.
  • Кликаем нексколько раз на кнопке, добавляющей ряды. "Спрятавшееся" значение оказывается на своем законном месте в таблице.
Вот такая интересная фигня. Побороть ее несложно. Вопрос в том как побороть ее наиболее грамотно?

Вот код программы:
Код

import java.awt.BorderLayout;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;

public class TableRowsAddRemove extends JFrame {


    private JTable jTable = new JTable(1, 1);

    public TableRowsAddRemove(){

        //Create table

        //VARIANTS A and B
        
        this.add(jTable, BorderLayout.CENTER);
        
        //VARIANT C
        
        //this.add(new JScrollPane(jTable), BorderLayout.CENTER);
        
        //Create buttons

        JButton button = new JButton("Add row");
        button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addRowToTable();
            }
        });
        this.add(button, BorderLayout.WEST);

        button = new JButton("Remove empty rows");
        button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeEmptyRowsFromTable();
            }
        });
        this.add(button, BorderLayout.EAST);

        //Finalise the window

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(800, 600);
        this.setVisible(true);

    }//end constructor

    public static void main(String[] args) {

        new TableRowsAddRemove();                
    }

    //PRIVATE METHODS

    private void addRowToTable(){
        ((DefaultTableModel)jTable.getModel()).addRow(new String[0]);
    }

    private void removeEmptyRowsFromTable(){
        DefaultTableModel model = (DefaultTableModel)jTable.getModel();
        
        int nCols = model.getColumnCount();
        boolean rowIsEmpty;
        Object oValue;
        
        for(int r = model.getRowCount() - 1; r >=0; r--){
            
            rowIsEmpty = true;
            
            for(int c = 0; c < nCols; c++){
                oValue = model.getValueAt(r, c);
                if(oValue != null && (! "".equals(oValue.toString().trim()))){
                    rowIsEmpty = false;
                    break;
                }
            }
            
            if(rowIsEmpty){
                model.removeRow(r);
            }        
        }
    }

}


Автор: jk1 31.12.2010, 14:51
Мне известно два способа решения проблемы.
Первый:
Код

table.getCellEditor(row, column).stopCellEditing();

его можно вызывать для каждой ячейки каждого удаляемого столбца. Решение, прямо скажем, далекое от оптимального.
Второй способ - конфигурирование самой таблицы. При создании нужно будет сделать следующее:
Код

jTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

При попытке нажатия на кнопку таблица теряет фокус и, согласно установленному property, выходит из режима редактирования автоматически.

Автор: _Y_ 31.12.2010, 15:18
jk1, спасибо, jTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); рулит. Я до такого простого решения не додумался.

Кстати, а где бы посмотреть как и почему это ClientProperty функционирует?

Автор: jk1 31.12.2010, 16:42
Цитата

Кстати, а где бы посмотреть как и почему это ClientProperty функционирует? 

Client Properties - это механизм, обеспечивающий унификацию механизма задания различных свойств. Если посмотреть внимательно, то оказывается что он реализован в JComponent и наследуется подавляющим большинством Swing-компонент. На уровне конкретного компонента определяется только то, какие property он способен понять и применить. Ничего экстраординарного в этой модели нет, можно было бы с тем же успехом наделать специфических методов для каждого компонента. А изнутри компонента совершенно все равно каким образом было установлено то или иное свойство поведения\состояния.

Внутри компонента Client Properties хранятся в отдельной хэш-таблице.

Таким образом, Client Properties - всего лишь еще один способ конфигурирования Swing-компонент, наряду с setXXX() методами. Для справки можно пользоваться http://www.chka.de/swing/components/client_properties.html.

Что меня всегда удивляло, так это отсутствие нормальной документации от производителя по этому вопросу. И, кстати, гарантий работы этого механизма в будущем тоже. 

Автор: _Y_ 31.12.2010, 19:41
jk1, теперь вроде понятно. Про такой хэш я знал. Чего не знал - что добавляя в таблицу Property уже определенное в данном компоненте (ссылка, которую ты привел), устанавливаешь значение этого Property.

Спасибо! smile

Автор: dorogoyIV 1.1.2011, 12:02
+ для jk1 (_Y_ с тебя), реально заслужил  smile 

Автор: _Y_ 1.1.2011, 12:18
dorogoyIV, а я сразу должное отдал smile  Как только ответ прочитал.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)