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


Автор: BlHol 11.1.2009, 16:34
День добрый!
Вопрос такой. Создал таблицу, заполнил. Теперь нужно на ячейку таблицы повесить листенер, действия в котором, выполняются в зависимости от значения в ячейке. Вопрос - как?
Если можно, общий алгоритм и пару методов. 
Заранее спасибо.
С уважением.

Автор: fixxer 11.1.2009, 17:03
Можно usecase поподробнее, что именно нужно и в какой момент?

Автор: BlHol 11.1.2009, 17:09
Цитата(fixxer @ 11.1.2009,  17:03)
Можно usecase поподробнее, что именно нужно и в какой момент?

Вобщем ситуация такая. Есть таблица с различными значениями. Если ячейка содержит значение отличное от нуля, то при клике на ней должна разворачиваться (под данной таблицей) еще одна таблица с расшифровкой данного значения ячейки.
Заранее спасибо.

Автор: fixxer 11.1.2009, 17:46
если я правильно понял, что речь идет о JTable (кстати в таком случае вопрос стоит задать в разделе по Java GUI), то можно повесится на изменение выделения строк (JTable#getSelectionModel().addSelectionListener(...)) и на изменение выделения колонок (JTable#getColumnModel().addColumnModelListener(...)). Можно объединить эти два листенера в одном классе и при изменении выделения проверять значение в модели таблицы и действовать соответствующим образом.

Автор: skif18 12.1.2009, 14:52
fixxer, а примерчик или ссылку на что-то подобное не подбросишь? Автор опередил с темой ...   smile 

Автор: LSD 13.1.2009, 15:40
Ещё как вариант можно использовать MouseListener и rowAtPoint() + columnAtPoint() (поищи по форуму, примеры как их использовать я уже давал).

Автор: BlHol 14.1.2009, 13:08
Цитата(LSD @ 13.1.2009,  15:40)
Ещё как вариант можно использовать MouseListener и rowAtPoint() + columnAtPoint() (поищи по форуму, примеры как их использовать я уже давал).

Спасибо. Попробую. Хотя, честно говоря, получилось через MouseListener, повешеным на таблицу с оценкой выделенной строки и столбца. 
Теперь появилась новая проблема. Нужно те ячейки, где число отличное от нуля как-то выделить (цветом, жирным шрифтом и т.д.). Усложняется все тем, что в таблице не только числовые данные. Причем, в разных строках  и ячейках.

Заранее спасибо.
С уважением.

Автор: Connie 14.1.2009, 14:51
BlHol, а рендер с этим не справится?
http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#renderer

Автор: fixxer 14.1.2009, 15:48
Код

public class JTableTest {

    public static void main(String[] args) {
        JFrame frame = new JFrame("JTable test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JTable table = new JTable(new Object[][]{
                    {0, "test1", "test2"},
                    {"test3", 1, "test4"},
                    {"test5", "test6", 2}},
                new String[]{"one", "two", "three"}
                );

        final JLabel label = new JLabel("info");

        ListSelectionListener listener = new ListSelectionListener() {

            public void valueChanged(ListSelectionEvent e) {
                if (!e.getValueIsAdjusting()) {
                    Object value = table.getModel().getValueAt(
                            table.getSelectedRow(), table.getSelectedColumn());
                    label.setText(value + " " + value.getClass().getSimpleName());
                }
            }
        };

        table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.getSelectionModel().addListSelectionListener(listener);
        table.getColumnModel().getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.getColumnModel().getSelectionModel().addListSelectionListener(listener);

        table.setDefaultRenderer(Object.class, new BoldCellRenderer());

        frame.getContentPane().add(new JScrollPane(table));
        frame.getContentPane().add(label, BorderLayout.SOUTH);

        frame.setBounds(100, 100, 640, 480);
        frame.setVisible(true);
    }

    private static class BoldCellRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            if (value instanceof Integer && ((Integer) value) > 0) {
                c.setFont(c.getFont().deriveFont(Font.BOLD));
            }
            return c;
        }

    }

}

Автор: BlHol 14.1.2009, 17:05
Спасибо! Реально, грамотно!
Сейчас, чуть подкорректирую и в код.

Еще раз, огроменнейшее спасибо!

Автор: BlHol 14.1.2009, 17:38
fixxer
Еще один вопросик, если Вас не затруднит.
Все, в общем, понятно.

Код

        table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.getSelectionModel().addListSelectionListener(listener);
        table.getColumnModel().getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.getColumnModel().getSelectionModel().addListSelectionListener(listener);


Не совсем понятна необходимость повторного навешивания Листенера и повторной установки выделения  (3 и 4 строки)


И еще один вопросик.
Есть ли смысл написать класс, который будет рендерить любую таблицу (в зависимости, скажем, от некоего флага), переданную в него или лучше просто каждый раз навешивать на новую таблицу новый рендерер?


С уважением.

Автор: fixxer 15.1.2009, 01:46
Цитата(BlHol @ 14.1.2009,  17:38)
fixxer
Еще один вопросик, если Вас не затруднит.
Все, в общем, понятно.

Код

        table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.getSelectionModel().addListSelectionListener(listener);
        table.getColumnModel().getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.getColumnModel().getSelectionModel().addListSelectionListener(listener);


Не совсем понятна необходимость повторного навешивания Листенера и повторной установки выделения  (3 и 4 строки)


И еще один вопросик.
Есть ли смысл написать класс, который будет рендерить любую таблицу (в зависимости, скажем, от некоего флага), переданную в него или лучше просто каждый раз навешивать на новую таблицу новый рендерер?


С уважением.

Внимательнее! Листенер присоединяется к различным источникам, изменение выделения сторок и выделения колонок, соответственно.

По-поводу универсальности. Зачастую универсальные классы замусориваются в процесе разработки деталями и адаптациями к конкретным решениям. Думаю, что полезно руководствоваться тем, что класс должен хорошо выполнять одну конкретную хорошо очерченую задачу. (Single Responsibility). Но единого ответа тут быть не может - нужно  решать в каждом конкретном случае.

Автор: math64 15.1.2009, 09:18
Нужно добавить TableModelListener (если есть возможность редактирования таблицы):
Код

class TableSelectionListener implements ListeSelectionListener, TableModelListener {
   JTable table;
   JLabel label;
   int row, col;
   Object value;
   public TableSelectionListener(JTable table, JLabel label) {
     this.table = table;
     this.label = label;
     table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
     table.getSelectionModel().addListSelectionListener(this);
     table.getColumnModel().getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
     table.getColumnModel().getSelectionModel().addListSelectionListener(this);
     table.getModel().addTableModelListener(this);
   }
   public void valueChanged(ListSelectionEvent e) {
       if (!e.getValueIsAdjusting()) {
         row = table.getSelectedRow();
         col = table.getSelectedColumn();
         showValue(table.getModel().getValueAt(row, col));
       }
    }
    private void showValue(Object newValue) {
       if (newValue == value)
         return;
       value = newValue;
       if (value != null)
         label.setText(value + " " + value.getClass().getSimpleName());
       else
         label.setText("null value");
   }
   public void tableChanged(TableModelEvent e) {
      showValue(table.getModel().getValueAt(row, col));
   }
}

Автор: BlHol 15.1.2009, 10:52
Цитата(fixxer @ 15.1.2009,  01:46)
Внимательнее! Листенер присоединяется к различным источникам, изменение выделения сторок и выделения колонок, соответственно.


Это я видел, что к разным. Просто, в случае с 
Код

table.getColumnModel().getSelectionModel().addListSelectionListener(listener);

понятно, что вешается на столбец.
А в случае с 
Код

table.getSelectionModel().addListSelectionListener(listener);

это как-то не очень понятно, куда он вешается...

Автор: skif18 15.1.2009, 11:28
Код

jTable.addMouseListener(new java.awt.event.MouseListener() {
                public void mouseReleased(java.awt.event.MouseEvent e) {
                    //  Код действия...
                }

Пользовался этим. Работает.

Автор: math64 15.1.2009, 14:30
Когда вешаешь обработчик MouseListener реакия идёт только на мышь, при ListSelectionListener можно управлять клавиатурой или программно - содержимое метки будет изменяться, но если нет TableModelListener, содержимое метки не будет изменяться при изменении содержимого ячейки таблицы если остаётся выделена та же самая ячейка.

Автор: x8m6 15.1.2009, 16:41
Цитата

А в случае с 
Выделить всёБез подсветки
1:
    
table.getSelectionModel().addListSelectionListener(listener);

это как-то не очень понятно, куда он вешается... 

На строки соответственно

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