Java图形化:Swing表格的使用

利用JTable类直接创建表格

创建表格:

在JTable类中除了默认的构造方法之外,还提供了利用指定表格列名数组和表格数据数组创建表格的构造方法,如下:

JTable(Object[][] rowData,Object[] columnNames)

  • rowData就是表格的数据数组
  • columnNames就是表格的列名数组。

使用表格时,一般将其添加到滚动面板中,然后将滚动面板加到相应的位置。

在JTable中还提供了利用指定表格的列名向量和表格数据向量创造表格的构造方法,如下:
JTable(Vector rowData,Vector columnNames)

  • rowDara就是表格的数据向量
  • columnNames就是表格的列名向量

在使用表格时,有时候不需要使用滚动条,就可以在窗体中显示整个表格,在这种情况下,也可以直接将表格添加到相应的容器中。

注意:如果是将表格添加到相应的容器中,则需要通过JTable类的getTableHeader()方法获得JTableHeader类的对象,然后再将该对象添加到容器的相应位置,否则表格将没有列名。

简单表格案例:

package view.flight;

import javax.swing.*;
import java.awt.*;

/**
 * @author: 我的袜子都是洞
 */
public class TestGui extends JFrame {
    // 列名
    String[] columnName = new String[]{"航班号", "出发时间", "飞行时间", "出发地", "目的地", "余票", "票价"};
    // 表格具体数据
    String[][] columnDate = new String[][]{
            {"1", "2019-01-18 10:05", "90分钟", "北京", "纽约", "50", "500.0"},
            {"2", "2019-01-18 10:05", "90分钟", "北京", "纽约", "10", "500.0"},
            {"3", "2019-01-18 10:05", "90分钟", "北京", "纽约", "10", "500.0"},
            {"4", "2019-01-18 10:05", "90分钟", "北京", "纽约", "40", "500.0"},
    };
    JTable table = new JTable(columnDate, columnName);

    TestGui(String title) {
        super(title);
        init();
        setComponent ();
        addComponent();
        addListener();
        setVisible(true);
    }
    private void init () {
        setSize(600, 400);
        // 设置窗口位置居中
        setLocationRelativeTo(null);
        // 设置布局
        setLayout(new BorderLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    private void setComponent () {
        // 设置第一列宽度为40
        table.getColumnModel().getColumn(0).setPreferredWidth(40);
        // 设置第二列宽度为120
        table.getColumnModel().getColumn(1).setPreferredWidth(120);
        
    }
    private void addComponent () {
        // 使用srcllpane会自动显示列名
        JScrollPane scrollPane = new JScrollPane(table);
        add(scrollPane, BorderLayout.CENTER);
    }
    private void addListener () {

    }
    public static void main(String[] args) {
        new TestGui("JTable演示");
    }
}
JTable界面

定制表格

表格创建之后,还需要对其进行一系列的定义,以便适合于具体的使用情况。默认情况下双击单元格便可对其编辑,如果不需要此功能,可以通过重构JTable类的isCellEditable(int row,int column)方法实现该方法返回boolean型值true,表示可以编辑,否则返回false则表示不可编辑。

可通过JTableHeader类的setReorderingAllowed(boolean reorderAllowed)方法设置表格是否支持重新排列功能,该方法返回boolean型值true表示支持,返回false表示不支持。

默认情况下,单元格中的内容左侧显示,如果需要居中显示,可通过重构JTable类的getDefaultRenderer(Class<?> columnClass)方法来实现。
重构的代码:

public TableCellRenderer getDefaultRenderer(Class<?> columnClass) {
    DefaultTableCellRenderer cr=(DefaultTableCellRenderer)super.getDefaultRenderer(columnClass);
    cr.setHorizontalAlignment(DefaultTableCellRenderer.CENTER);
    return cr;
}

JTable类的用来定义表格的常用方法

  • setRowHeight(int rowHeight):设置表格的行高,默认像素为16
  • setRowSelectionAllowed(boolean sa):设置是否允许选中表格行,默认为允许选中,设为false表示不允许选中
  • setSelectionMode(int sm):设置表格行的选中模式
  • setSelectionBackground(Color cr):设置表格选中行的背景色
  • setSelectionForeground(Color fc):设置表格选中行的前景色
  • setAutoResizeMode(int mode):设置表格的自动调整模式

在利用setSelectionMode(int sm)方法设置表格行的选择模式时,它的入口参数从ListSelectionModel的静态常量中选择。如下:

  • 静态常量:SINGLE_SELECTION,常量值:0,表示只选择一个。
  • 静态常量:SINGLE_INTERVAL_SELECTION,常量值:1,表示允许连续选择多个
  • 静态常量:MULTIPLE_INTERVAL_SELECTION,常量值:2,表示随意选择多个

在利用setAutoResizeMode(int mode)方法设置表格的自动调整模式时,它的入口参数从JTable类的静态常量中选择。

注意:表格的自动调整模式,就是在调整表格的某一列的宽度时,表格采用何种方式保持其总宽度不变。

操纵表格

在编写应用程序时,经常需要获得表格的一些信息,如下是JTable类中的三个经常用来获得表格信息的方法。

  • getRowCount():获得表格拥有的行数,返回值为int型。
  • getColumnCount():获得表格拥有的列数,返回值为int型。
  • getColumnName(int column):获得位于指定索引位置的列的名称,返回值为String型。

JTable类中经常用来操纵表格选中行的方法如下:

  • setRowSelectionInterval(int from,int to):选中行索引从from到to的所有行(包括索引为from到to的行)
  • addRowSelectionInterval(int from,int to):将行索引从from到to的所有行追加为表格的选中行
  • isRowSelected(int row):查看行索引为row的行是否被选中
  • selectAll():选中表格中的所有行
  • clearSelection():取消所有选中行的选择状态
  • getSelectedRowCount():得到选中行的数量,返回值为int型,如果没有被选中的行,则返回-1
  • getSelectedRow():得到被选中的行中最小的索引值,返回值为int型,如果没有被选中的行,则返回-1
    -getSelectedRows():获得所有被选中行的索引值,返回值为int数组

表格模型和表格

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

  • public int getRowCount()
  • public int getColumnCount()
  • public Object getValueAt(int rowIndex,int columnIndex)

通过继承AbstractTableModel可以实现上面的3个抽象方法可以创建自己的表格模型类。DefaultTableModel类便是由Swing类提供的继承了AbstractTableModel类并实现了上面3个抽象方法的表格模型类。

从JDK1.6开始,提供了对表格进行排序的功能。通过JTable类的setRowSorter(RowSorter<? extends TableModel> sorter)方法可以为表格设置排序器。TableRowSorter类是由Swing提供的排序类,为表格设置排序器的代码如下:

DefaultTableModel tableModel=new DefaultTableModel();
JTable table=new JTable(tableModel);
table.setRowSorter(new TableRowSorter(tableModel));

在使用表格排序器时,通常需要为其设置表格模型,一种方法是通过构造方法TableRowSorter(TableModel model),另一种方法是通过setModel(TableModel model)方法为表格排序器设置表格模型。

维护表格模型

使用表格时,需要经常对表格中的内容进行维护,如向表格中添加新的数据行、修改表格中某一单元格的值、从表格中删除数据行等,这些操作都可以通过维护表格模型来完成。

在向表格模型中添加新的数据行时有两种情况:一种是添加到表格模型的尾部,另一种是添加到表格模型指定的索引处,分别由addRow(Object[] rowData)insertRow(int row,Object[] rowData)addRow(Vector rowData)insertRow(int row,Vector rowData)方法实现。

如果需要修改表格模型中某一个单元格的数据,可以通过方法setValueAt(Object aValue,int row,int column)完成,其中aValue就是修改后的值,可以通过getValueAt(int row,int column)获得单元格的值,该方法返回Object型。

如果需要删除表格模型中某一行的数据,可以通过方法removeRow(int row)来完成,其中row为欲要删除行的索引。

使用TableModel模型案例:

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.awt.*;

/**
 * @author: 我的袜子都是洞
 */
public class TestGui extends JFrame {

    JTable table = new JTable(new FlightTableModel());

    TestGui(String title) {
        super(title);
        init();
        setComponent ();
        addComponent();
        addListener();
        setVisible(true);
    }
    private void init () {
        setSize(600, 400);
        // 设置窗口位置居中
        setLocationRelativeTo(null);
        // 设置布局
        setLayout(new BorderLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    private void setComponent () {
        // 设置第一列宽度为40
        table.getColumnModel().getColumn(0).setPreferredWidth(40);
        // 设置第二列宽度为120
        table.getColumnModel().getColumn(1).setPreferredWidth(120);

    }
    private void addComponent () {
        // 使用srcllpane会自动显示列名
        JScrollPane scrollPane = new JScrollPane(table);
        add(scrollPane, BorderLayout.CENTER);
    }
    private void addListener () {

    }
    public static void main(String[] args) {
        new TestGui("JTable演示");
    }
}

class FlightTableModel extends AbstractTableModel {
    // 列名
    String[] columnName = new String[]{"航班号", "出发时间", "飞行时间", "出发地", "目的地", "余票", "票价"};
    // 表格具体数据
    String[][] flightDate = new String[][]{
            {"1", "2019-01-18 10:05", "90分钟", "北京", "纽约", "50", "500.0"},
            {"2", "2019-01-18 10:05", "90分钟", "北京", "纽约", "10", "500.0"},
            {"3", "2019-01-18 10:05", "90分钟", "北京", "纽约", "10", "500.0"},
            {"4", "2019-01-18 10:05", "90分钟", "北京", "纽约", "40", "500.0"},
    };
    /**
     * 返回一共多少行
     */
    @Override
    public int getRowCount() {
        return flightDate.length;
    }

    /**
     * 返回一共多少列
     */
    @Override
    public int getColumnCount() {
        return columnName.length;
    }

    /**
     * 返回每一个单元格的值
     */
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return flightDate[rowIndex][columnIndex];
    }

    /**
     * 获取每一列的名称
     */
    @Override
    public String getColumnName(int column) {
        return columnName[column];
    }

    /**
     * 单元格是否可以修改
     */
    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }
}

效果:


使用TableModel的案例

通过监听选中单元格获取对应数据的实例:

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import java.awt.*;

/**
 * @author: 我的袜子都是洞
 */
public class TestGui extends JFrame {
    FlightTableModel flight = new FlightTableModel();
    JTable table = new JTable(flight);

    TestGui(String title) {
        super(title);
        init();
        setComponent ();
        addComponent();
        addListener();
        setVisible(true);
    }
    private void init () {
        setSize(600, 400);
        // 设置窗口位置居中
        setLocationRelativeTo(null);
        // 设置布局
        setLayout(new BorderLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    private void setComponent () {
        // 设置第一列宽度为40
        table.getColumnModel().getColumn(0).setPreferredWidth(40);
        // 设置第二列宽度为120
        table.getColumnModel().getColumn(1).setPreferredWidth(120);

    }
    private void addComponent () {
        // 使用srcllpane会自动显示列名
        JScrollPane scrollPane = new JScrollPane(table);
        add(scrollPane, BorderLayout.CENTER);
    }
    private void addListener () {
        // selection监听器监听表格哪行被选中
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                // 被选中的行
                int row = table.getSelectedRow();
                String str = (String)flight.getValueAt(row,0);
                System.out.println("选中的行号是:"+row+",航班号是:"+str);
            }
        });
    }
    public static void main(String[] args) {
        new TestGui("JTable演示");
    }
}

class FlightTableModel extends AbstractTableModel {
    // 列名
    String[] columnName = new String[]{"航班号", "出发时间", "飞行时间", "出发地", "目的地", "余票", "票价"};
    // 表格具体数据
    String[][] flightDate = new String[][]{
            {"1", "2019-01-18 10:05", "90分钟", "北京", "纽约", "50", "500.0"},
            {"2", "2019-01-18 10:05", "90分钟", "北京", "纽约", "10", "500.0"},
            {"3", "2019-01-18 10:05", "90分钟", "北京", "纽约", "10", "500.0"},
            {"4", "2019-01-18 10:05", "90分钟", "北京", "纽约", "40", "500.0"},
    };
    /**
     * 返回一共多少行
     */
    @Override
    public int getRowCount() {
        return flightDate.length;
    }

    /**
     * 返回一共多少列
     */
    @Override
    public int getColumnCount() {
        return columnName.length;
    }

    /**
     * 返回每一个单元格的值
     */
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return flightDate[rowIndex][columnIndex];
    }

    /**
     * 获取每一列的名称
     */
    @Override
    public String getColumnName(int column) {
        return columnName[column];
    }

    /**
     * 单元格是否可以修改
     */
    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }
}

关键部分:

// selection监听器监听表格哪行被选中
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                // 被选中的行
                int row = table.getSelectedRow();
                String str = (String)flight.getValueAt(row,0);
                System.out.println("选中的行号是:"+row+",航班号是:"+str);
            }
        });

获取到的结果图:
窗口图:


窗口

数据:


数据
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342