Реагируем на выделение строк в JTable таблице

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

Если посмотреть на таблицу JTable, то она чем-то похожа на список. Действительно здесь имеется список строк, которые пользователь может выделять различным образом — по одной или несколько сразу. Для работы с такими выделенными строками у JTable есть «модель выделения» selection model, а именно ListSelectionModel. К ней добавляются слушатели, которые хотят быть уведомленными о том, что пользователь выделил какие-то строки в таблице. Чтобы добраться до неё, разработчик должен вызвать метод getSelectionModel. Далее потребуется реализовать интерфейс ListSelectionListener с одним единственным методом valueChanged, который будет вызываться у слушателя при выделении строк в таблице. Ну а затем добавим этого слушателя к selection model с помощью метода addListSelectionListener.

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

jtable_selection

Думаю стоит рассмотреть код обработчика выделения более подробнее. Для того, чтобы отобразить названия выделенных элементов, необходимо узнать, какие строки в таблице оказались выдлены. Делается это с помощью вызова метода getSelectedRows у JTable. Метод возвращает массив индексов выделенных строк. Далее нужно перебрать этот массив, для каждой выделенной строк получить название элемента (значение из нужного столбца, а именно Name). Перебирать массивы думаю умеем. Для получения нужного значения из строки необходимо обратиться к модели таблицы JTable. Именно через модель можно получить доступ ко всем отображаемым значениям — сама таблица данных не содержит, а лишь показывает их пользователю. Для получения модели используется метод getModel у JTable. Чтобы получить из модели значение используем метод getValueAt, в который передается индекс строки, а также индекс столбца — таким образом получаем значение, которое показывается в ячейки таблицы JTable. Значение получено, формируем результат и отображаем его.

Код приложения представлен ниже.


import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableModel;

public class TestFrame extends JFrame {

     public static void createGUI() {
          JFrame frame = new JFrame("Test frame");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

          String[] columnNames = {
                    "Name",
                    "Last modified",
                    "Type",
                    "Size"
          };
          
          String[][] data = {
                    {"addins", "02.11.2006 19:15", "Folder", ""},
                    {"AppPatch", "03.10.2006 14:10", "Folder", ""},
                    {"assembly", "02.11.2006 14:20", "Folder", ""},
                    {"Boot", "13.10.2007 10:46", "Folder", ""},
                    {"Branding", "13.10.2007 12:10", "Folder", ""},
                    {"Cursors", "23.09.2006 16:34", "Folder", ""},
                    {"Debug", "07.12.2006 17:45", "Folder", ""},
                    {"Fonts", "03.10.2006 14:08", "Folder", ""},
                    {"Help", "08.11.2006 18:23", "Folder", ""}
          };
          
          JPanel mainPanel = new JPanel();
          mainPanel.setLayout(new BorderLayout());
          
          final JTable table = new JTable(data, columnNames);          
          JScrollPane scrollPane = new JScrollPane(table);
          mainPanel.add(scrollPane, BorderLayout.CENTER);
          
          JPanel bottomPanel = new JPanel();
          bottomPanel.setLayout(new FlowLayout(FlowLayout.LEFT));          
          
          JLabel selLabel = new JLabel("Selected:");
          bottomPanel.add(selLabel);
          
          final JLabel currentSelectionLabel = new JLabel("");
          currentSelectionLabel.setAutoscrolls(true);          
          bottomPanel.add(currentSelectionLabel);
          
          mainPanel.add(bottomPanel, BorderLayout.SOUTH);
          
          ListSelectionModel selModel = table.getSelectionModel();
          
          selModel.addListSelectionListener(new ListSelectionListener() {               
               public void valueChanged(ListSelectionEvent e) {
                    String result = "";
                    int[] selectedRows = table.getSelectedRows();
                    for(int i = 0; i < selectedRows.length; i++) {
                         int selIndex = selectedRows[i];
                         TableModel model = table.getModel();
                         Object value = model.getValueAt(selIndex, 0);
                         result = result + value;
                         if(i != selectedRows.length — 1) {
                               result += ", ";
                         }
                    }
                    currentSelectionLabel.setText(result);                    
               }               
          });
          
          frame.getContentPane().add(mainPanel);
          
          frame.setPreferredSize(new Dimension(550, 200));
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
     }

     public static void main(String[] args) {
          javax.swing.SwingUtilities.invokeLater(new Runnable() {
               public void run() {
                    JFrame.setDefaultLookAndFeelDecorated(true);
                    createGUI();
               }
          });
     }
}

12 Responses to Реагируем на выделение строк в JTable таблице

  1. painter says:

    Вот недавно столкнулся с одной задачей… как реализовать обработку события двойного щелчка мыши на выделенной строке таблице?

  2. painter says:

    Вообщем, кому интерено, можно посмотреть здесь:
    http://www.rgagnon.com/javadetails/java-0336.html

  3. Посетитель says:

    Автору большое спасибо за статью! Нигде так понятно и просто не описывается материал.

  4. wm.Aster says:

    Программа не компилируется как есть.. убрал из строчки: if(i != selectedRows.length – 1)
    -1 и все заработало как надо.

  5. Игорь says:

    странно, у меня таким образом сообщение два раза выводится

  6. ASVShade says:

    Обновите символ «-» в строке:
    if(i != selectedRows.length — 1) {

    У него там кодировка некомпилируемая

  7. EvGeniy says:

    final JTable table …

    как сделать чтобы JTable table не объявлять final потому как у меня в зависимости от выбора 4 разных модели таблицы создаются. а потом надо отлавливать выделение строк

    и если я делаю не final то вот тут

    int[] selectedRows = table.getSelectedRows();

    то он говорит что ее надо сделать final

  8. fen1x says:

    подскажите пожалуйста, как можно получить доступ к строчкам в таблице? Допустим, если хотим эти строки использовать в другой программе. Или например, чтобы вывести какую-то из строк на экран в другом классе?

Оставьте комментарий