表格组件

Swing 表格由 JTable 对象表示,其作用是把数据以表格的形式显示给用户。本节将对 Swing 表格组件进行讲解。

创建表格

JTable 类除提供了默认的构造方法外,还提供了用于显示二维数组中的元素的构造方法,这个构造方法的语法如下:

     JTable(Object[][] rowData, Object[] columnNames)
  • rowData:存储表格数据的二维数组。

  • columnNames:存储表格列名的一维数组。

在使用表格时,要先把表格添加到滚动面板中,再把滚动面板添加到窗体的相应位置处。

【例18.22】创建带滚动条的表格(实例位置:资源包\TM\sl\18\22)

利用构造方法 JTable(Object[][] rowData, Object[] columnNames) 创建一个具有滚动条的表格。

import java.awt.*;
import javax.swing.*;
public class JTableDemo extends JFrame {
    public static void main(String args[]) {
        JTableDemo frame = new JTableDemo();
        frame.setVisible(true);
    }
    public JTableDemo() {
        setTitle("创建可以滚动的表格");
        setBounds(100, 100, 240, 150);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        String[] columnNames = {"A", "B"};                  // 定义表格列名数组
        // 定义表格数据数组
        String[][] tableValues = {{"A1", "B1"}, {"A2", "B2"}, {"A3", "B3"},
                {"A4", "B4"}, {"A5", "B5"}};
        // 创建指定列名和数据的表格
        JTable table = new JTable(tableValues, columnNames);
        // 创建显示表格的滚动面板
        JScrollPane scrollPane = new JScrollPane(table);
        // 将滚动面板添加到边界布局的中间
        getContentPane().add(scrollPane, BorderLayout.CENTER);
    }
}

运行结果如图18.27所示。当窗体的高度变小时,将出现滚动条,效果图如图18.28所示。

image 2024 03 05 23 20 22 271
Figure 1. 图18.27 滚动条未出现时的表格
image 2024 03 05 23 20 45 496
Figure 2. 图18.28 滚动条出现时的表格

DefaultTableModel表格数据模型

Swing 使用 TableModel 接口定义了一个表格模型,AbstractTableModel 抽象类实现了 TableModel 接口的大部分方法,只有以下 3 个抽象方法没有实现:

  • public int getRowCount()。

  • public int getColumnCount()。

  • public Object getValueAt(int rowIndex, int columnIndex)。

为了实现使用表格模型创建表格的功能, Swing 提供了表格模型类,即 DefaultTableModel 类。DefaultTableModel 类继承了 AbstractTableModel 抽象类且实现了上述 3 个抽象方法。DefaultTableModel 类提供的常用构造方法如表18.8所示。

image 2024 03 05 23 22 32 840
Figure 3. 表18.8 DefaultTableModel类提供的常用构造方法

表格模型被创建后,使用 JTable 类的构造方法 JTable(TableModel dm) 即可创建表格。表格被创建后,还可以使用 setRowSorter() 方法为表格设置排序器:当单击表格的某一列的列头时,在这一列的列名后将出现▲标记,说明将按升序排列表格中的所有行;当再次单击这一列的列头时,标记将变为▼,说明按降序排列表格中的所有行。

【例18.23】表格自动排序(实例位置:资源包\TM\sl\18\23)

利用表格模型创建表格,并对表格使用表格排序器。

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class SortingTable extends JFrame {
    private static final long serialVersionUID = 1L;
    public static void main(String args[]) {
        SortingTable frame = new SortingTable();
        frame.setVisible(true);
    }
    public SortingTable() {
        setTitle("表格模型与表格");
        setBounds(100, 100, 240, 150);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JScrollPane scrollPane = new JScrollPane();
        getContentPane().add(scrollPane, BorderLayout.CENTER);
        String[] columnNames = {"A", "B"};               // 定义表格列名数组
        // 定义表格数据数组
        String[][] tableValues = {{"A1", "B1"}, {"A2", "B2"}, {"A3", "B3"}}; 
        // 创建指定表格列名和表格数据的表格模型
        DefaultTableModel tableModel = new DefaultTableModel(tableValues, columnNames);  
        JTable table = new JTable(tableModel);         // 创建指定表格模型的表格
        table.setRowSorter(new TableRowSorter<>(tableModel));
        scrollPane.setViewportView(table);
    }
}

运行结果如图18.29所示。单击名称为B的列头后,将得到如图18.30所示的效果,此时 B 列的数据按升序排列;再次单击名称为 B 的列头后,将得到如图18.31所示的效果,此时 B 列的数据按降序排列。

image 2024 03 05 23 24 11 324
Figure 4. 图18.29 运行效果
image 2024 03 05 23 24 37 017
Figure 5. 图18.30 升序排列
image 2024 03 05 23 25 02 231
Figure 6. 图18.31 降序排列

维护表格模型

表格中的数据内容需要予以维护,如使用 getValueAt() 方法获得表格中某一个单元格的值,使用 addRow() 方法向表格中添加新的行,使用 setValueAt() 方法修改表格中某一个单元格的值,使用 removeRow() 方法从表格中删除指定行等。

当删除表格模型中的指定行时,每删除一行,其后所有行的索引值将相应地减 1,因此当连续删除多行时,需要注意对删除行索引的处理。

【例18.24】对表格内容进行增删改查(实例位置:资源包\TM\sl\18\24)

维护表格模型。本例通过维护表格模型,实现向表格中添加新的数据行、修改表格中某一单元格的值以及从表格中删除指定的数据行。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class AddAndDeleteDemo extends JFrame {
    private DefaultTableModel tableModel;          // 定义表格模型对象
    private JTable table;                            // 定义表格对象
    private JTextField aTextField;
    private JTextField bTextField;
    public static void main(String args[]) {
        AddAndDeleteDemo frame = new AddAndDeleteDemo();
        frame.setVisible(true);
    }
    public AddAndDeleteDemo() {
        setTitle("维护表格模型");
        setBounds(100, 100, 530, 200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JScrollPane scrollPane = new JScrollPane();
        getContentPane().add(scrollPane, BorderLayout.CENTER);
        String[] columnNames = {"A", "B"};          // 定义表格列名数组
         // 定义表格数据数组
        String[][] tableValues = {{"A1", "B1"}, {"A2", "B2"}, {"A3", "B3"}}; 
        // 创建指定表格列名和表格数据的表格模型
        tableModel = new DefaultTableModel(tableValues, columnNames);
        table = new JTable(tableModel);                // 创建指定表格模型的表格
        table.setRowSorter(new TableRowSorter<>(tableModel));     // 设置表格的排序器
        // 设置表格的选择模式为单选
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        // 为表格添加鼠标事件监听器
        table.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {         // 发生了单击事件
                int selectedRow = table.getSelectedRow();    // 获得被选中行的索引
                // 从表格模型中获得指定单元格的值
                Object oa = tableModel.getValueAt(selectedRow, 0);
                // 从表格模型中获得指定单元格的值
                Object ob = tableModel.getValueAt(selectedRow, 1);
                aTextField.setText(oa.toString());           // 将值赋值给文本框
                bTextField.setText(ob.toString());           // 将值赋值给文本框
            }
        });
        scrollPane.setViewportView(table);
        JPanel panel = new JPanel();
        getContentPane().add(panel, BorderLayout.SOUTH);
        panel.add(new JLabel("A:"));
        aTextField = new JTextField("A4", 10);
        panel.add(aTextField);
        panel.add(new JLabel("B:"));
        bTextField = new JTextField("B4", 10);
        panel.add(bTextField);
        JButton addButton = new JButton("添加");
        addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String[] rowValues = {aTextField.getText(),
                        bTextField.getText()};              // 创建表格行数组
                tableModel.addRow(rowValues);              // 向表格模型中添加一行
                int rowCount = table.getRowCount() + 1;
                aTextField.setText("A" + rowCount);
                bTextField.setText("B" + rowCount);
            }
        });
        panel.add(addButton);
        JButton updButton = new JButton("修改");
        updButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int selectedRow = table.getSelectedRow();  // 获得被选中行的索引
                if (selectedRow != -1) {                     // 判断是否存在被选中行
                    // 修改表格模型当中的指定值
                    tableModel.setValueAt(aTextField.getText(), selectedRow, 0); 
                    // 修改表格模型当中的指定值
                    tableModel.setValueAt(bTextField.getText(), selectedRow, 1); 
                }
            }
        });
        panel.add(updButton);
        JButton delButton = new JButton("删除");
        delButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int selectedRow = table.getSelectedRow();  // 获得被选中行的索引
                if (selectedRow != -1)                        // 判断是否存在被选中行
                    tableModel.removeRow(selectedRow);       // 从表格模型当中删除指定行
            } 
        });
        panel.add(delButton);
    }
}

运行结果如图18.32所示。其中,A、B 文本框分别用来编辑 A、B 列中单元格的数据内容。当单击 “添加” 按钮时,可以将编辑好的数据内容添加到表格中;当选中表格的某一行时,在 A、B 文本框中将分别显示对应列的信息。重新编辑表格中某一个单元格的值后,单击 “修改” 按钮即可修改被选中的单元格的值;当单击 “删除” 按钮时,可以删除表格中被选中的行。

编程训练(答案位置:资源包\TM\sl\18\编程训练)

【训练15】人员信息表(一) 创建一个表格,显示如图18.33所示的内容。

image 2024 03 05 23 27 40 778
Figure 7. 图18.32 维护表格模型
image 2024 03 05 23 28 05 786
Figure 8. 图18.33 效果示意图

【训练16】人员信息表(二) 在训练15中添加一个“删除”按钮,单击“删除”按钮可以删除已选中的行。