我可以通过单击任何列对 JTable 进行排序,但我还需要使用键盘对 JTable 进行排序。
是否有内置方法可以通过键盘以相同的方式进行排序,或者我是否必须添加某种侦听器?
我创建了一个示例 GUI,允许用户使用键盘对
JTable
进行排序。 JTable
必须具有 table.setColumnSelectionAllowed(true);
和 table.setRowSelectionAllowed(false);
才能使此应用程序正常工作。
这是 GUI 的样子。
您可以通过左键单击列标题对列进行排序。 您还可以使用以下键盘按键对列进行排序。 (感谢@Just 另一位 Java 程序员的评论。)
不按 CTRL 的左右箭头也会选择一列。 为了保持一致性,我决定使用 CTRL +。 默认左右箭头不会选择排序列。
这是完整的可运行代码。 我制作了所有附加类的内部类,这样我就可以将代码作为一个块发布。
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
public class SortJTable implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new SortJTable());
}
private int columnIndexToSort;
private final Company company;
private JTable table;
public SortJTable() {
this.company = new Company();
this.columnIndexToSort = -1;
}
@Override
public void run() {
JFrame frame = new JFrame("Sort JTable");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTablePanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createTablePanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
EmployeeTableModel tableModel = new EmployeeTableModel();
Employee[] employees = company.getEmployees();
for (Employee employee : employees) {
tableModel.addRow(employee);
}
table = new JTable(tableModel);
table.getColumnModel().getColumn(2)
.setCellRenderer(new SalaryCellRenderer());
table.setAutoCreateRowSorter(true);
table.setColumnSelectionAllowed(true);
table.setRowSelectionAllowed(false);
setKeyBindings(table);
JScrollPane scrollPane = new JScrollPane(table);
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
private void setKeyBindings(JTable table) {
InputMap inputMap = table.getInputMap();
ActionMap actionMap = table.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP,
InputEvent.CTRL_DOWN_MASK), "ctrl up");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,
InputEvent.CTRL_DOWN_MASK), "ctrl down");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,
InputEvent.CTRL_DOWN_MASK), "ctrl left");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,
InputEvent.CTRL_DOWN_MASK), "ctrl right");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,
InputEvent.CTRL_DOWN_MASK), "ctrl space");
actionMap.put("ctrl up",
new SortColumnAction(this, SortOrder.ASCENDING));
actionMap.put("ctrl down",
new SortColumnAction(this, SortOrder.DESCENDING));
actionMap.put("ctrl left", new SelectColumnAction(this, -1));
actionMap.put("ctrl right", new SelectColumnAction(this, +1));
actionMap.put("ctrl space",
new SortColumnAction(this, SortOrder.UNSORTED));
}
public JTable getTable() {
return table;
}
public int getColumnIndexToSort() {
return columnIndexToSort;
}
public void setColumnIndexToSort(int columnIndexToSort) {
this.columnIndexToSort = columnIndexToSort;
}
public class SelectColumnAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private final int columnCount, increment;
private final SortJTable view;
public SelectColumnAction(SortJTable view, int increment) {
this.view = view;
this.increment = increment;
this.columnCount = view.getTable().getColumnCount();
}
@Override
public void actionPerformed(ActionEvent event) {
int columnIndexToSort = view.getColumnIndexToSort();
columnIndexToSort += increment;
columnIndexToSort %= columnCount;
columnIndexToSort = (columnIndexToSort < 0)
? columnIndexToSort + columnCount
: columnIndexToSort;
JTable table = view.getTable();
table.removeColumnSelectionInterval(0, table.getColumnCount() - 1);
table.addColumnSelectionInterval(columnIndexToSort,
columnIndexToSort);
view.setColumnIndexToSort(columnIndexToSort);
}
}
public class SortColumnAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private final SortJTable view;
private final SortOrder sortOrder;
public SortColumnAction(SortJTable view, SortOrder sortOrder) {
this.view = view;
this.sortOrder = sortOrder;
}
@Override
public void actionPerformed(ActionEvent event) {
int columnIndexToSort = view.getColumnIndexToSort();
columnIndexToSort = Math.max(0, columnIndexToSort);
JTable table = view.getTable();
TableRowSorter<TableModel> sorter = new TableRowSorter<>(
table.getModel());
table.setRowSorter(sorter);
List<RowSorter.SortKey> sortKeys = new ArrayList<>();
sortKeys.add(new RowSorter.SortKey(columnIndexToSort, sortOrder));
sorter.setSortKeys(sortKeys);
sorter.sort();
// table.addColumnSelectionInterval(columnIndexToSort, columnIndexToSort);
}
}
public class SalaryCellRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1L;
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
JLabel label = (JLabel) super.getTableCellRendererComponent(table,
value, isSelected, hasFocus, row, column);
int salary = (Integer) value;
label.setText("$" + String.format("%,d", salary) + " ");
label.setHorizontalAlignment(JLabel.TRAILING);
return label;
}
}
public class EmployeeTableModel extends DefaultTableModel {
private static final long serialVersionUID = 1L;
public EmployeeTableModel() {
super();
String[] columns = { "Name", "Title", "Salary" };
this.setColumnIdentifiers(columns);
}
public void addRow(Employee employee) {
Object[] newRow = new Object[3];
newRow[0] = employee.getName();
newRow[1] = employee.getTitle();
newRow[2] = employee.getSalary();
this.addRow(newRow);
}
@Override
public Class<?> getColumnClass(int column) {
if (column == 2) {
return Integer.class;
} else {
return String.class;
}
}
}
public class Company {
private final Employee[] employees;
public Company() {
this.employees = new Employee[10];
this.employees[0] = new Employee("Smith, John", "Senior Analyst",
75_000);
this.employees[1] = new Employee("White, Susan", "Junior Analyst",
35_200);
this.employees[2] = new Employee("Baker, Nancy", "Senior Analyst",
75_600);
this.employees[3] = new Employee("Potter, Harry", "Junior Analyst",
36_100);
this.employees[4] = new Employee("Smythe, Frank", "Analyst",
52_700);
this.employees[5] = new Employee("Accosta, Sue", "Senior Analyst",
75_000);
this.employees[6] = new Employee("Baker, Veronica", "Analyst",
50_500);
this.employees[7] = new Employee("Green, Maggie", "Analyst",
52_700);
this.employees[8] = new Employee("Wesson, James", "Analyst",
52_700);
this.employees[9] = new Employee("Ericson, Leif", "Analyst",
51_400);
}
public Employee[] getEmployees() {
return employees;
}
}
public class Employee {
private int salary;
private String name, title;
public Employee(String name, String title, int salary) {
this.name = name;
this.title = title;
this.salary = salary;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
}