Реагируем на выделение строк в JTable таблице
6 августа, 2009 12 комментариев
При работе с JTable иногда возникает необходимость реагировать на действия пользователя, а именно на выделение строк в таблице. Как и в других аналогичных случаях, здесь понадобится повесить нужного слушателя и реализовать код, который будет выполняться при выделении строк пользователем.
Если посмотреть на таблицу JTable, то она чем-то похожа на список. Действительно здесь имеется список строк, которые пользователь может выделять различным образом — по одной или несколько сразу. Для работы с такими выделенными строками у JTable есть «модель выделения» selection model, а именно ListSelectionModel. К ней добавляются слушатели, которые хотят быть уведомленными о том, что пользователь выделил какие-то строки в таблице. Чтобы добраться до неё, разработчик должен вызвать метод getSelectionModel. Далее потребуется реализовать интерфейс ListSelectionListener с одним единственным методом valueChanged, который будет вызываться у слушателя при выделении строк в таблице. Ну а затем добавим этого слушателя к selection model с помощью метода addListSelectionListener.
Для более лучшего понимания предлагаю посмотреть пример простого приложения, внешний вид которого представлен на рисунке ниже. Приложение состоит из таблицы со списком файлов. Как только пользователь выделяет в таблице что-то, это немедленно отражается снизу — отображается список элементов через запятую, которые пользователь выделил. Выделять можно сразу несколько элементов.
Думаю стоит рассмотреть код обработчика выделения более подробнее. Для того, чтобы отобразить названия выделенных элементов, необходимо узнать, какие строки в таблице оказались выдлены. Делается это с помощью вызова метода 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();
}
});
}
}
Вот недавно столкнулся с одной задачей… как реализовать обработку события двойного щелчка мыши на выделенной строке таблице?
Вообщем, кому интерено, можно посмотреть здесь:
http://www.rgagnon.com/javadetails/java-0336.html
Автору большое спасибо за статью! Нигде так понятно и просто не описывается материал.
Программа не компилируется как есть.. убрал из строчки: if(i != selectedRows.length – 1)
-1 и все заработало как надо.
Поправлю
странно, у меня таким образом сообщение два раза выводится
Обновите символ «-» в строке:
if(i != selectedRows.length — 1) {
У него там кодировка некомпилируемая
проблема в скобках
Хотя да, я уже чушь несу:)
final JTable table …
как сделать чтобы JTable table не объявлять final потому как у меня в зависимости от выбора 4 разных модели таблицы создаются. а потом надо отлавливать выделение строк
и если я делаю не final то вот тут
int[] selectedRows = table.getSelectedRows();
то он говорит что ее надо сделать final
Можно вынести локальную переменную в свойства основного класса.
подскажите пожалуйста, как можно получить доступ к строчкам в таблице? Допустим, если хотим эти строки использовать в другой программе. Или например, чтобы вывести какую-то из строк на экран в другом классе?