Тип слушателя для обновлений заданных ячеек/столбцов в JTable и увеличения фокуса

Я пытаюсь использовать JTable с предопределенным первым столбцом. Пользователь вводит данные только во 2-й столбец (Количество). Затем я рассчитываю окончательный доход, умножая столбцы «Услуга» и «Количество», и отображаю его в третьем столбце «Доход».

|Service | Quantity | Income
|$40.00  | X        | 
|$40.00  | 3        | 120 

Здесь пользователь вводит «3», потому что сегодня она оказала «3» услуги X по 40 долларов за каждую. Пользователь может обновлять только столбец Количество. Столбец «Доход» будет рассчитан системой.

Какой тип слушателя я должен использовать? Я использовал TableModelListener, но когда я хочу обновить Income до 120, вызвав setValue = $120, он запускает TableListenerEvent и, следовательно, бесконечный цикл.

Должен ли я использовать ActionEvent, ColumnListener или что-то еще?

Кроме того, я хочу, чтобы «фокус» увеличивал строки вниз, всегда оставаясь во втором столбце (столбец, который редактирует пользователь).


person DeeDee    schedule 25.08.2011    source источник


Ответы (1)


для просмотра изменений в TableCell необходимо реализовать TableModelListener Например

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

import java.awt.event.KeyEvent;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

public class TableProcessing extends JFrame {

    private static final long serialVersionUID = 1L;
    private JTable table;
    private String[] columnNames = {"Item", "Quantity", "Price", "Cost"};
    private Object[][] data = {
        {"Bread", new Integer(1), new Double(1.11), new Double(1.11)},
        {"Milk", new Integer(1), new Double(2.22), new Double(2.22)},
        {"Tea", new Integer(1), new Double(3.33), new Double(3.33)},
        {"Cofee", new Integer(1), new Double(4.44), new Double(4.44)}};
    private TableModelListener tableModelListener;

    public TableProcessing() {
        DefaultTableModel model = new DefaultTableModel(data, columnNames);
        table = new JTable(model) {

            private static final long serialVersionUID = 1L;

            @Override// Returning the Class of each column will allow different renderers
            public Class getColumnClass(int column) { // to be used based on Class
                return getValueAt(0, column).getClass();
            }

            @Override //  The Cost is not editable
            public boolean isCellEditable(int row, int column) {
                int modelColumn = convertColumnIndexToModel(column);
                return (modelColumn == 3) ? false : true;
            }
        };
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        //http://stackoverflow.com/questions/7188179/jtable-focus-query/7193023#7193023
        table.setCellSelectionEnabled(true);
        KeyStroke tab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
        InputMap map = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        map.put(tab, "selectNextRowCell");
        //http://stackoverflow.com/questions/7188179/jtable-focus-query/7193023#7193023
        JScrollPane scrollPane = new JScrollPane(table);
        getContentPane().add(scrollPane);
        setTableModelListener();
    }

    private void setTableModelListener() {
        tableModelListener = new TableModelListener() {

            @Override
            public void tableChanged(TableModelEvent e) {
                if (e.getType() == TableModelEvent.UPDATE) {
                    System.out.println("Cell " + e.getFirstRow() + ", "
                            + e.getColumn() + " changed. The new value: "
                            + table.getModel().getValueAt(e.getFirstRow(),
                            e.getColumn()));
                    int row = e.getFirstRow();
                    int column = e.getColumn();
                    if (column == 1 || column == 2) {
                        TableModel model = table.getModel();
                        int quantity = ((Integer) model.getValueAt(row, 1)).intValue();
                        double price = ((Double) model.getValueAt(row, 2)).doubleValue();
                        Double value = new Double(quantity * price);
                        model.setValueAt(value, row, 3);
                    }
                }
            }
        };
        table.getModel().addTableModelListener(tableModelListener);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                TableProcessing frame = new TableProcessing();
                frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}
person mKorbel    schedule 25.08.2011
comment
+1 за переопределение isCellEditable(); см. также этот Вопросы и ответы относительно направления табуляции. - person trashgod; 26.08.2011
comment
спасибо, код обновлен, но теперь я вижу реальные требования для tips4java.wordpress.com/? s=table+selectall от @camickr :-) - person mKorbel; 26.08.2011
comment
Я вижу вашу точку зрения. Хорошая ссылка на обе статьи @camickr, которая станет хорошим упражнением для читателя. - person trashgod; 26.08.2011