本文目录导读:

我来详细介绍Java Swing中JTable表格的数据展示和编辑功能。
基本JTable创建
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
public class JTableDemo extends JFrame {
public JTableDemo() {
setTitle("JTable示例");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600, 400);
setLocationRelativeTo(null);
// 创建表格数据
String[] columnNames = {"ID", "姓名", "年龄", "性别", "部门"};
Object[][] data = {
{1, "张三", 28, "男", "技术部"},
{2, "李四", 32, "女", "市场部"},
{3, "王五", 25, "男", "人事部"},
{4, "赵六", 30, "女", "财务部"}
};
// 创建表格
JTable table = new JTable(data, columnNames);
// 添加到滚动面板
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane, BorderLayout.CENTER);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new JTableDemo().setVisible(true);
});
}
}
使用TableModel实现数据编辑
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
// 自定义数据模型
class Employee {
private int id;
private String name;
private int age;
private String gender;
private String department;
private double salary;
// 构造器、getter/setter
public Employee(int id, String name, int age, String gender, String department, double salary) {
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
this.department = department;
this.salary = salary;
}
// getter和setter方法
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getGender() { return gender; }
public void setGender(String gender) { this.gender = gender; }
public String getDepartment() { return department; }
public void setDepartment(String department) { this.department = department; }
public double getSalary() { return salary; }
public void setSalary(double salary) { this.salary = salary; }
}
// 自定义表格模型
class EmployeeTableModel extends AbstractTableModel {
private String[] columnNames = {"ID", "姓名", "年龄", "性别", "部门", "薪资"};
private List<Employee> employees;
private boolean[] editableColumns = {false, true, true, true, true, true}; // ID列不可编辑
public EmployeeTableModel(List<Employee> employees) {
this.employees = employees;
}
@Override
public int getRowCount() {
return employees.size();
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public String getColumnName(int column) {
return columnNames[column];
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Employee emp = employees.get(rowIndex);
switch (columnIndex) {
case 0: return emp.getId();
case 1: return emp.getName();
case 2: return emp.getAge();
case 3: return emp.getGender();
case 4: return emp.getDepartment();
case 5: return emp.getSalary();
default: return null;
}
}
@Override
public void setValueAt(Object value, int rowIndex, int columnIndex) {
Employee emp = employees.get(rowIndex);
switch (columnIndex) {
case 1: emp.setName((String) value); break;
case 2: emp.setAge(Integer.parseInt(value.toString())); break;
case 3: emp.setGender((String) value); break;
case 4: emp.setDepartment((String) value); break;
case 5: emp.setSalary(Double.parseDouble(value.toString())); break;
}
fireTableCellUpdated(rowIndex, columnIndex);
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return editableColumns[columnIndex];
}
// 获取指定行的数据类型
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0: return Integer.class;
case 2: return Integer.class;
case 5: return Double.class;
default: return String.class;
}
}
public void addEmployee(Employee emp) {
employees.add(emp);
fireTableRowsInserted(employees.size() - 1, employees.size() - 1);
}
public void removeEmployee(int row) {
employees.remove(row);
fireTableRowsDeleted(row, row);
}
}
// 使用示例
public class EditableJTableDemo extends JFrame {
private EmployeeTableModel tableModel;
private JTable table;
public EditableJTableDemo() {
setTitle("可编辑的JTable示例");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 500);
setLocationRelativeTo(null);
// 准备初始数据
List<Employee> employees = new ArrayList<>();
employees.add(new Employee(1, "张三", 28, "男", "技术部", 8000.0));
employees.add(new Employee(2, "李四", 32, "女", "市场部", 7500.0));
employees.add(new Employee(3, "王五", 25, "男", "人事部", 6500.0));
// 创建表格模型和表格
tableModel = new EmployeeTableModel(employees);
table = new JTable(tableModel);
// 设置表格属性
table.setRowHeight(30);
table.setFont(new Font("微软雅黑", Font.PLAIN, 14));
table.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 14));
// 设置列宽
table.getColumnModel().getColumn(0).setPreferredWidth(50);
table.getColumnModel().getColumn(1).setPreferredWidth(100);
table.getColumnModel().getColumn(5).setPreferredWidth(100);
// 滚动面板
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane, BorderLayout.CENTER);
// 控制面板
JPanel controlPanel = new JPanel();
JButton addBtn = new JButton("添加行");
JButton deleteBtn = new JButton("删除选中行");
JButton saveBtn = new JButton("保存数据");
addBtn.addActionListener(e -> addRow());
deleteBtn.addActionListener(e -> deleteSelectedRow());
saveBtn.addActionListener(e -> saveData());
controlPanel.add(addBtn);
controlPanel.add(deleteBtn);
controlPanel.add(saveBtn);
add(controlPanel, BorderLayout.SOUTH);
}
private void addRow() {
int newId = tableModel.getRowCount() + 1;
Employee emp = new Employee(newId, "新员工", 20, "男", "待分配", 5000.0);
tableModel.addEmployee(emp);
}
private void deleteSelectedRow() {
int selectedRow = table.getSelectedRow();
if (selectedRow != -1) {
int confirmed = JOptionPane.showConfirmDialog(
this,
"确认删除第 " + (selectedRow + 1) + " 行?",
"确认删除",
JOptionPane.YES_NO_OPTION
);
if (confirmed == JOptionPane.YES_OPTION) {
tableModel.removeEmployee(selectedRow);
}
} else {
JOptionPane.showMessageDialog(this, "请先选择要删除的行");
}
}
private void saveData() {
// 停止单元格编辑
if (table.isEditing()) {
table.getCellEditor().stopCellEditing();
}
// 这里可以保存数据到数据库或文件
JOptionPane.showMessageDialog(this, "数据保存成功!");
// 打印当前数据
System.out.println("当前数据:");
for (int i = 0; i < tableModel.getRowCount(); i++) {
for (int j = 0; j < tableModel.getColumnCount(); j++) {
System.out.print(tableModel.getValueAt(i, j) + "\t");
}
System.out.println();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new EditableJTableDemo().setVisible(true);
});
}
}
单元格编辑器定制
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.text.NumberFormat;
// 自定义单元格编辑器
public class CustomCellEditorDemo extends JFrame {
public CustomCellEditorDemo() {
setTitle("自定义单元格编辑器");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600, 400);
setLocationRelativeTo(null);
// 创建表格数据
String[] columnNames = {"姓名", "年龄", "性别", "城市", "评分"};
Object[][] data = {
{"张三", 28, "男", "北京", 85.5},
{"李四", 32, "女", "上海", 92.3},
{"王五", 25, "男", "广州", 78.0}
};
JTable table = new JTable(data, columnNames);
// 为性别列设置下拉框编辑器
JComboBox<String> genderCombo = new JComboBox<>(new String[]{"男", "女"});
TableColumn genderColumn = table.getColumnModel().getColumn(2);
genderColumn.setCellEditor(new DefaultCellEditor(genderCombo));
// 为年龄列设置数字限制
TableColumn ageColumn = table.getColumnModel().getColumn(1);
ageColumn.setCellEditor(new DefaultCellEditor(new JTextField()) {
@Override
public boolean stopCellEditing() {
try {
String value = (String) getCellEditorValue();
int age = Integer.parseInt(value);
if (age < 0 || age > 150) {
throw new NumberFormatException();
}
return super.stopCellEditing();
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(
CustomCellEditorDemo.this,
"请输入有效的年龄 (0-150)",
"输入错误",
JOptionPane.ERROR_MESSAGE
);
return false;
}
}
});
// 为城市列设置自动完成文本框
JTextField cityField = new JTextField();
TableColumn cityColumn = table.getColumnModel().getColumn(3);
cityColumn.setCellEditor(new DefaultCellEditor(cityField));
// 设置表格属性
table.setRowHeight(30);
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new CustomCellEditorDemo().setVisible(true);
});
}
}
单元格渲染器定制
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
// 自定义单元格渲染器
public class CustomCellRendererDemo extends JFrame {
public CustomCellRendererDemo() {
setTitle("自定义单元格渲染器");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600, 400);
setLocationRelativeTo(null);
// 创建表格数据
String[] columnNames = {"姓名", "年龄", "性别", "成绩", "状态"};
Object[][] data = {
{"张三", 28, "男", 85, "及格"},
{"李四", 32, "女", 45, "不及格"},
{"王五", 25, "男", 92, "优秀"},
{"赵六", 30, "女", 60, "及格"},
{"钱七", 27, "男", 38, "不及格"}
};
JTable table = new JTable(data, columnNames);
// 自定义成绩列渲染器
TableColumn scoreColumn = table.getColumnModel().getColumn(3);
scoreColumn.setCellRenderer(new 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);
int score = (int) value;
if (score >= 90) {
c.setBackground(new Color(144, 238, 144)); // 浅绿色
c.setForeground(Color.BLACK);
} else if (score >= 60) {
c.setBackground(new Color(255, 255, 224)); // 浅黄色
c.setForeground(Color.BLACK);
} else {
c.setBackground(new Color(255, 182, 193)); // 浅红色
c.setForeground(Color.RED);
}
if (isSelected) {
c.setBackground(c.getBackground().darker());
}
setHorizontalAlignment(CENTER);
return c;
}
});
// 自定义状态列渲染器
TableColumn statusColumn = table.getColumnModel().getColumn(4);
statusColumn.setCellRenderer(new StatusCellRenderer());
// 自定义性别列显示
TableColumn genderColumn = table.getColumnModel().getColumn(2);
genderColumn.setCellRenderer(new 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);
String gender = (String) value;
if ("男".equals(gender)) {
setIcon(new ImageIcon("male_icon.png")); // 使用图标
setText("♂ " + gender);
} else {
setIcon(new ImageIcon("female_icon.png"));
setText("♀ " + gender);
}
setHorizontalAlignment(CENTER);
return c;
}
});
// 交替行颜色
table.setRowHeight(30);
table.setFont(new Font("微软雅黑", Font.PLAIN, 14));
// 设置表格外观
table.setShowGrid(true);
table.setGridColor(Color.LIGHT_GRAY);
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
}
// 自定义状态渲染器
class StatusCellRenderer 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);
String status = (String) value;
switch (status) {
case "优秀":
setBackground(new Color(0, 128, 0));
setForeground(Color.WHITE);
break;
case "及格":
setBackground(new Color(255, 165, 0));
setForeground(Color.BLACK);
break;
case "不及格":
setBackground(new Color(255, 0, 0));
setForeground(Color.WHITE);
break;
}
if (isSelected) {
setBackground(setBackground.getDarker());
}
setHorizontalAlignment(CENTER);
setFont(getFont().deriveFont(Font.BOLD));
return c;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new CustomCellRendererDemo().setVisible(true);
});
}
}
高级功能:多选和排序
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.util.Comparator;
public class AdvancedJTableDemo extends JFrame {
public AdvancedJTableDemo() {
setTitle("高级JTable功能");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 500);
setLocationRelativeTo(null);
String[] columnNames = {"编号", "姓名", "年龄", "薪资", "入职日期"};
Object[][] data = {
{1, "张三", 28, 8000.0, "2023-01-15"},
{2, "李四", 32, 9500.0, "2022-06-20"},
{3, "王五", 25, 7000.0, "2024-03-01"},
{4, "赵六", 30, 8800.0, "2023-09-10"}
};
DefaultTableModel model = new DefaultTableModel(data, columnNames) {
@Override
public Class<?> getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
@Override
public boolean isCellEditable(int row, int column) {
return column > 0; // 除了编号都可以编辑
}
};
JTable table = new JTable(model);
// 启用自动排序
table.setAutoCreateRowSorter(true);
// 设置选择模式
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
// 设置列宽
table.getColumnModel().getColumn(0).setPreferredWidth(60);
table.getColumnModel().getColumn(1).setPreferredWidth(100);
table.getColumnModel().getColumn(2).setPreferredWidth(60);
table.getColumnModel().getColumn(3).setPreferredWidth(100);
table.getColumnModel().getColumn(4).setPreferredWidth(120);
// 自定义排序器(按年龄排序时特殊处理)
TableRowSorter<TableModel> sorter = new TableRowSorter<>(model);
sorter.setComparator(2, (Integer o1, Integer o2) -> o1.compareTo(o2));
table.setRowSorter(sorter);
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane, BorderLayout.CENTER);
// 添加选择监听
table.getSelectionModel().addListSelectionListener(e -> {
if (!e.getValueIsAdjusting()) {
int[] selectedRows = table.getSelectedRows();
if (selectedRows.length > 0) {
StringBuilder sb = new StringBuilder("选中的行: ");
for (int row : selectedRows) {
int modelRow = table.convertRowIndexToModel(row);
sb.append("行").append(modelRow + 1).append(" ");
}
System.out.println(sb.toString());
}
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new AdvancedJTableDemo().setVisible(true);
});
}
}
注意事项
- 性能优化:大数据量时使用虚拟模式
- 线程安全:Swing组件操作应在EDT线程中进行
- 数据验证:在
setValueAt()中进行数据验证 - 模型-视图分离:尽量使用TableModel而非直接操作数据
这些示例涵盖了JTable的展示、编辑、自定义渲染和高级功能,可以根据具体需求进行调整和扩展。