JTabe 通过按键盘上的键选择/突出显示行
JTabe selecting / highlighting row(s) by pressing a key on keyboard
我有一个实际上有 4 列和很多行的 JTable。现在我想通过按键盘上的一个键来 select 一行或多行。但我不知道该怎么做。
这是我想要的例子:
- 如果我在键盘上按 "F",我的应用程序应该 select 或突出显示我的 table 中的第一行,其中有一个以字符 "F" 开头的条目(或另一个我按
- 如果我再次按同一个键(此处 "F"),则应该 select 或突出显示下一行,该行的条目以字符 "F"[=19 开头=]
- 如果最后一行被 select 编辑并且我再次按下相同的键它应该 select 或再次突出显示第一行(循环)
- 当我按下另一个键时,例如 "U",它应该像上面那样对以 "U" 开头的行执行相同的操作。
这听起来是个有趣的问题。所以我破解了一些可以作为您解决方案基础的东西。注意:您可以通过适当的封装和泛型进一步改进这一点。
警告:仅当您的 table 数据模型很小时才使用它。如果它很大,您应该考虑一些更好的搜索方法以及 concurrency/UI 反馈以避免您的 UI 冻结。
无论如何,解决方案将与下面类似。关键是向 table 添加一个按键侦听器,然后根据 row/col 值检查按键字符。 HTH
package example;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
/** Extend default model to make cells non-editable */
class MyTableModel extends DefaultTableModel {
public MyTableModel(Object[][] data, Object[] headers) {
super(data, headers);
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
}
/** Key listener that controls row highlighting */
class SearchingKeyAdapter extends KeyAdapter {
private final JTable table;
private int selectedRow = -1;//before start
public SearchingKeyAdapter(JTable table) {
this.table = table;
}
@Override
public void keyReleased(KeyEvent e) {
String keyChar = String.valueOf(e.getKeyChar());
TableModel model = table.getModel();
int startRow = selectedRow;
if (selectedRow == model.getRowCount() - 1) {
startRow = -1;//Go before start
}
//Check each cell to see if it starts with typed char.
//if so set corresponding row selected and return.
for (int row = startRow+1; row < model.getRowCount(); row++) {
for (int col = 0; col < model.getColumnCount(); col++) {
String value = (String) model.getValueAt(row, col);
if (value != null && value.startsWith(keyChar)) {
table.getSelectionModel().clearSelection();
table.getColumnModel().getSelectionModel().clearSelection();
table.setRowSelectionInterval(row, row);
selectedRow = row;
return;
}
}
}
}
}
public class App {
JFrame frame;
JTable table;
String[][] data = {
{"for", "util", "synchronized", "final"}, {"finally", "throw", "throws", "try"}, {"import", "class", "interface", "if"}, {"public", "private", "protected", "volatile"}
};
String[] headers = {"Keyword1", "Keyword2", "Keyword3", "Keyword3"};
public App() {
table = new JTable();
table.setModel(new MyTableModel(data, headers));
//Add special key listener that will move highlight based on typed char
table.addKeyListener(new SearchingKeyAdapter(table));
//We need to have only single selection
table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
frame = new JFrame();
frame.setLayout(new BorderLayout());
JScrollPane scrollPane = new JScrollPane();
scrollPane.getViewport().add(table);
frame.getContentPane().add(scrollPane);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
App app = new App();
}
});
}
}
我有一个实际上有 4 列和很多行的 JTable。现在我想通过按键盘上的一个键来 select 一行或多行。但我不知道该怎么做。
这是我想要的例子:
- 如果我在键盘上按 "F",我的应用程序应该 select 或突出显示我的 table 中的第一行,其中有一个以字符 "F" 开头的条目(或另一个我按
- 如果我再次按同一个键(此处 "F"),则应该 select 或突出显示下一行,该行的条目以字符 "F"[=19 开头=]
- 如果最后一行被 select 编辑并且我再次按下相同的键它应该 select 或再次突出显示第一行(循环)
- 当我按下另一个键时,例如 "U",它应该像上面那样对以 "U" 开头的行执行相同的操作。
这听起来是个有趣的问题。所以我破解了一些可以作为您解决方案基础的东西。注意:您可以通过适当的封装和泛型进一步改进这一点。 警告:仅当您的 table 数据模型很小时才使用它。如果它很大,您应该考虑一些更好的搜索方法以及 concurrency/UI 反馈以避免您的 UI 冻结。 无论如何,解决方案将与下面类似。关键是向 table 添加一个按键侦听器,然后根据 row/col 值检查按键字符。 HTH
package example;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
/** Extend default model to make cells non-editable */
class MyTableModel extends DefaultTableModel {
public MyTableModel(Object[][] data, Object[] headers) {
super(data, headers);
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
}
/** Key listener that controls row highlighting */
class SearchingKeyAdapter extends KeyAdapter {
private final JTable table;
private int selectedRow = -1;//before start
public SearchingKeyAdapter(JTable table) {
this.table = table;
}
@Override
public void keyReleased(KeyEvent e) {
String keyChar = String.valueOf(e.getKeyChar());
TableModel model = table.getModel();
int startRow = selectedRow;
if (selectedRow == model.getRowCount() - 1) {
startRow = -1;//Go before start
}
//Check each cell to see if it starts with typed char.
//if so set corresponding row selected and return.
for (int row = startRow+1; row < model.getRowCount(); row++) {
for (int col = 0; col < model.getColumnCount(); col++) {
String value = (String) model.getValueAt(row, col);
if (value != null && value.startsWith(keyChar)) {
table.getSelectionModel().clearSelection();
table.getColumnModel().getSelectionModel().clearSelection();
table.setRowSelectionInterval(row, row);
selectedRow = row;
return;
}
}
}
}
}
public class App {
JFrame frame;
JTable table;
String[][] data = {
{"for", "util", "synchronized", "final"}, {"finally", "throw", "throws", "try"}, {"import", "class", "interface", "if"}, {"public", "private", "protected", "volatile"}
};
String[] headers = {"Keyword1", "Keyword2", "Keyword3", "Keyword3"};
public App() {
table = new JTable();
table.setModel(new MyTableModel(data, headers));
//Add special key listener that will move highlight based on typed char
table.addKeyListener(new SearchingKeyAdapter(table));
//We need to have only single selection
table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
frame = new JFrame();
frame.setLayout(new BorderLayout());
JScrollPane scrollPane = new JScrollPane();
scrollPane.getViewport().add(table);
frame.getContentPane().add(scrollPane);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
App app = new App();
}
});
}
}