zoukankan      html  css  js  c++  java
  • 图形界面系列教材 (十)- Swing 使用 JTable详解

    步骤1:基本表格
    步骤2:JScrollPane
    步骤3:列宽
    步骤4:TableModel
    步骤5:进一步理解TableModel
    步骤6:TableModel 与DAO结合
    步骤7:TableSelectionModel
    步骤8:更新Table
    步骤9:输入项验证
    步骤10:选中指定行

    示例 1 : 基本表格

    显示一个Table需要两组数据 
    1. 一维数组: String[]columnNames 表示表格的标题 
    2. 二维数组: String[][] heros 表格中的内容 
    默认情况下,表格的标题是不会显示出来了,除非使用了JScrollPane

    基本表格

    package gui;

    import java.awt.BorderLayout;

    import javax.swing.JFrame;

    import javax.swing.JTable;

    public class TestGUI {

        public static void main(String[] args) {

            JFrame f = new JFrame("LoL");

            f.setSize(400300);

            f.setLocation(200200);

            f.setLayout(new BorderLayout());

            // 表格上的title

            String[] columnNames = new String[] { "id""name""hp""damage" };

            // 表格中的内容,是一个二维数组

            String[][] heros = new String[][] { { "1""盖伦""616""100" },

                    "2""提莫""512""102" }, { "3""奎因""832""200" } };

            JTable t = new JTable(heros, columnNames);

            f.add(t, BorderLayout.CENTER);

            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            f.setVisible(true);

        }

    }

    示例 2 : JScrollPane

    JScrollPane: 带滚动条的Panel 
    把table放进去就可以看到table的title 
    同样的把textarea放进去,并且textarea内容够长的话,就会看到滚动条

    JScrollPane

    package gui;

    import java.awt.BorderLayout;

    import javax.swing.JFrame;

    import javax.swing.JScrollPane;

    import javax.swing.JTable;

    public class TestGUI {

        public static void main(String[] args) {

            JFrame f = new JFrame("LoL");

            f.setSize(400300);

            f.setLocation(200200);

            f.setLayout(new BorderLayout());

            String[] columnNames = new String[] { "id""name""hp""damage" };

            String[][] heros = new String[][] { { "1""盖伦""616""100" },

                    "2""提莫""512""102" }, { "3""奎因""832""200" } };

            JTable t = new JTable(heros, columnNames);

            // 根据t创建 JScrollPane

            JScrollPane sp = new JScrollPane(t);

            //或则创建一个空的JScrollPane,再通过setViewportView把table放在JScrollPane中

            // JScrollPane sp = new JScrollPane(t);

            // sp.setViewportView(t);

            // 把sp而非JTable加入到JFrame上,

            f.add(sp, BorderLayout.CENTER);

            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            f.setVisible(true);

        }

    }

    示例 3 : 列宽

    设置列宽度

    列宽

    package gui;

    import java.awt.BorderLayout;

    import javax.swing.JFrame;

    import javax.swing.JScrollPane;

    import javax.swing.JTable;

    public class TestGUI {

        public static void main(String[] args) {

            JFrame f = new JFrame("LoL");

            f.setSize(400300);

            f.setLocation(200200);

            f.setLayout(new BorderLayout());

            String[] columnNames = new String[] { "id""name""hp""damage" };

            String[][] heros = new String[][] { { "1""盖伦""616""100" },

                    "2""提莫""512""102" }, { "3""奎因""832""200" } };

            JTable t = new JTable(heros, columnNames);

            JScrollPane sp = new JScrollPane(t);

            // 设置列宽度

            t.getColumnModel().getColumn(0).setPreferredWidth(10);

            f.add(sp, BorderLayout.CENTER);

            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            f.setVisible(true);

        }

    }

    示例 4 : TableModel

    首先说下TableModel的设计思想,在Model这种思想的指导下,数据和显示分离开来了。 比如对于JTable而言,有数据部分,也有显示部分(比如列宽等信息)。 数据部分,专门做一个类,叫做TableModel,就用于存放要显示的数据。

    使用TableModel的方式存放Table需要显示的数据
    HeroTableModel 继承AbstractTableModel ,进而实现了接口TableModel
    在HeroTableModel 中提供一个table显示需要的所有信息
    1. getRowCount 返回一共有多少行
    2. getColumnCount 返回一共有多少列
    3. getColumnName 每一列的名字
    4. isCellEditable 单元格是否可以修改
    5. getValueAt 每一个单元格里的值

    当图形界面需要渲染第一个单元格的数据的时候,就会调用方法TabelModel的getValueAt(0,0) ,把返回值拿到并显示

    package gui;

    import javax.swing.table.AbstractTableModel;

    public class HeroTableModel extends AbstractTableModel {

        String[] columnNames = new String[] { "id""name""hp""damage" };

        String[][] heros = new String[][] { { "1""盖伦""616""100" },

                "2""提莫""512""102" }, { "3""奎因""832""200" } };

        // 返回一共有多少行

        public int getRowCount() {

            // TODO Auto-generated method stub

            return heros.length;

        }

        // 返回一共有多少列

        public int getColumnCount() {

            // TODO Auto-generated method stub

            return columnNames.length;

        }

        // 获取每一列的名称

        public String getColumnName(int columnIndex) {

            // TODO Auto-generated method stub

            return columnNames[columnIndex];

        }

        // 单元格是否可以修改

        public boolean isCellEditable(int rowIndex, int columnIndex) {

            return false;

        }

        // 每一个单元格里的值

        public Object getValueAt(int rowIndex, int columnIndex) {

            // TODO Auto-generated method stub

            return heros[rowIndex][columnIndex];

        }

    }

    package gui;

      

    import java.awt.BorderLayout;

      

    import javax.swing.JFrame;

    import javax.swing.JScrollPane;

    import javax.swing.JTable;

      

    public class TestGUI {

        public static void main(String[] args) {

      

            JFrame f = new JFrame("LoL");

            f.setSize(400300);

            f.setLocation(200200);

            f.setLayout(new BorderLayout());

            //创建一个TableModel

            HeroTableModel htm= new HeroTableModel();

             

            //根据 TableModel来创建 Table

            JTable t = new JTable(htm);

      

            JScrollPane sp = new JScrollPane(t);

      

            f.add(sp, BorderLayout.CENTER);

      

            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      

            f.setVisible(true);

        }

    }

    示例 5 : 进一步理解TableModel

    在使用TableModel之前,是使用

    String[] columnNames =。。。

    String[][] heros = 。。。

    JTable t = new JTable(heros, columnNames);


    这样的风格创建一个JTable的
    所以实际上调用的是如下的构造方法:

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


    如图所示,在JTable的的源代码中,它就会根据rowData和columnNames去创建一个TableModel对象

    进一步理解TableModel

    示例 6 : TableModel 与DAO结合

    通过TableModel与DAO结合显示数据库中Hero信息。
    DAO使用HeroDAO
    在TableModel中,使用从DAO返回的List作为TableModel的数据

    只需要修改HeroTableModel,无需修改TestGUI。 这正好演绎了Model设计思想中的数据分离的好处,当只需要数据发生变化的时候,修改Model即可,界面GUI部分,不需要做任何改动

    TableModel 与DAO结合

    package gui;

    import java.util.List;

    import javax.swing.table.AbstractTableModel;

    import jdbc.HeroDAO;

    import charactor.Hero;

    public class HeroTableModel extends AbstractTableModel {

        String[] columnNames = new String[] { "id""name""hp""damage" };

        // 使用从DAO返回的List作为TableModel的数据

        public List<Hero> heros = new HeroDAO().list();

        // heros.size返回一共有多少行

        public int getRowCount() {

            // TODO Auto-generated method stub

            return heros.size();

        }

        public int getColumnCount() {

            // TODO Auto-generated method stub

            return columnNames.length;

        }

        public String getColumnName(int columnIndex) {

            // TODO Auto-generated method stub

            return columnNames[columnIndex];

        }

        public boolean isCellEditable(int rowIndex, int columnIndex) {

            return false;

        }

        // 先通过heros.get(rowIndex)获取行对应的Hero对象

        // 然后根据columnIndex返回对应的属性

        public Object getValueAt(int rowIndex, int columnIndex) {

            Hero h = heros.get(rowIndex);

            if (0 == columnIndex)

                return h.id;

            if (1 == columnIndex)

                return h.name;

            if (2 == columnIndex)

                return h.hp;

            if (3 == columnIndex)

                return h.damage;

            return null;

        }

    }

    示例 7 : TableSelectionModel

    通过table可以获取一个 TableSelectionModel,专门用于监听jtable选中项的变化

    TableSelectionModel

    package gui;

      

    import java.awt.BorderLayout;

      

    import javax.swing.JFrame;

    import javax.swing.JLabel;

    import javax.swing.JPanel;

    import javax.swing.JScrollPane;

    import javax.swing.JTable;

    import javax.swing.event.ListSelectionEvent;

    import javax.swing.event.ListSelectionListener;

      

    import charactor.Hero;

      

    public class TestGUI {

        public static void main(String[] args) {

      

            JFrame f = new JFrame("LoL");

            f.setSize(400300);

            f.setLocation(200200);

            f.setLayout(new BorderLayout());

      

            final HeroTableModel htm = new HeroTableModel();

      

            final JTable t = new JTable(htm);

            // 准备一个Panel上面放一个Label用于显示哪条被选中了

            JPanel p = new JPanel();

            final JLabel l = new JLabel("暂时未选中条目");

            p.add(l);

      

            JScrollPane sp = new JScrollPane(t);

      

            // 使用selection监听器来监听table的哪个条目被选中

            t.getSelectionModel().addListSelectionListener(

                    new ListSelectionListener() {

      

                        // 当选择了某一行的时候触发该事件

                        public void valueChanged(ListSelectionEvent e) {

                            // 获取哪一行被选中了

                            int row = t.getSelectedRow();

                            // 根据选中的行,到HeroTableModel中获取对应的对象

                            Hero h = htm.heros.get(row);

                            // 更新标签内容

                            l.setText("当前选中的英雄是: " + h.name);

      

                        }

                    });

      

            f.add(p, BorderLayout.NORTH);

            f.add(sp, BorderLayout.CENTER);

      

            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      

            f.setVisible(true);

        }

    }

    示例 8 : 更新Table

    以新增数据到数据库中,然后更新Table为例

    更新Table

    package gui;

    import java.awt.BorderLayout;

    import java.awt.Dimension;

    import java.awt.event.ActionEvent;

    import java.awt.event.ActionListener;

    import javax.swing.JButton;

    import javax.swing.JFrame;

    import javax.swing.JLabel;

    import javax.swing.JPanel;

    import javax.swing.JScrollPane;

    import javax.swing.JTable;

    import javax.swing.JTextField;

    import jdbc.HeroDAO;

    import charactor.Hero;

    public class TestGUI {

        public static void main(String[] args) {

            JFrame f = new JFrame("LoL");

            f.setSize(400300);

            f.setLocation(200200);

            f.setLayout(new BorderLayout());

            final HeroTableModel htm = new HeroTableModel();

            final JTable t = new JTable(htm);

            // 增加 一个 panel用于放置名称,血量输入框和增加 按钮

            JPanel p = new JPanel();

            final JLabel lName = new JLabel("名称");

            final JTextField tfName = new JTextField("");

            final JLabel lHp = new JLabel("血量");

            final JTextField tfHp = new JTextField("");

            JButton bAdd = new JButton("增加");

            tfName.setPreferredSize(new Dimension(8030));

            tfHp.setPreferredSize(new Dimension(8030));

            p.add(lName);

            p.add(tfName);

            p.add(lHp);

            p.add(tfHp);

            p.add(bAdd);

            // 为增加按钮添加监听

            bAdd.addActionListener(new ActionListener() {

                @Override

                public void actionPerformed(ActionEvent e) {

                    HeroDAO dao = new HeroDAO();

                    // 根据输入框数据创建一个Hero对象

                    Hero h = new Hero();

                    h.name = tfName.getText();

                    h.hp = Integer.parseInt(tfHp.getText());

                    // 通过dao把该对象加入到数据库

                    dao.add(h);

                    // 通过dao更新tablemodel中的数据

                    htm.heros = dao.list();

                    // 调用JTable的updateUI,刷新界面。

                    // 刷新界面的时候,会到tablemodel中去取最新的数据

                    // 就能看到新加进去的数据了

                    t.updateUI();

                }

            });

            JScrollPane sp = new JScrollPane(t);

            f.add(p, BorderLayout.NORTH);

            f.add(sp, BorderLayout.CENTER);

            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            f.setVisible(true);

        }

    }

    示例 9 : 输入项验证

    如果用户输入的名称为空,或者血量不是小数,在提交数据的时候都会报错。 
    “感觉上” 界面就卡住了。 这是不友好的人机交互行为。 
    所以需要加上输入项的验证,如果输入的数据不合格,应该弹出对话框提示用户具体原因。

    输入项验证

    package gui;

    import java.awt.BorderLayout;

    import java.awt.Dimension;

    import java.awt.event.ActionEvent;

    import java.awt.event.ActionListener;

    import javax.swing.JButton;

    import javax.swing.JFrame;

    import javax.swing.JLabel;

    import javax.swing.JOptionPane;

    import javax.swing.JPanel;

    import javax.swing.JScrollPane;

    import javax.swing.JTable;

    import javax.swing.JTextField;

    import jdbc.HeroDAO;

    import charactor.Hero;

    public class TestGUI {

        public static void main(String[] args) {

            final JFrame f = new JFrame("LoL");

            f.setSize(400300);

            f.setLocation(200200);

            f.setLayout(new BorderLayout());

            final HeroTableModel htm = new HeroTableModel();

            final JTable t = new JTable(htm);

            JPanel p = new JPanel();

            final JLabel lName = new JLabel("名称");

            final JTextField tfName = new JTextField("");

            final JLabel lHp = new JLabel("血量");

            final JTextField tfHp = new JTextField("");

            JButton bAdd = new JButton("增加");

            tfName.setPreferredSize(new Dimension(8030));

            tfHp.setPreferredSize(new Dimension(8030));

            p.add(lName);

            p.add(tfName);

            p.add(lHp);

            p.add(tfHp);

            p.add(bAdd);

            bAdd.addActionListener(new ActionListener() {

                @Override

                public void actionPerformed(ActionEvent e) {

                    HeroDAO dao = new HeroDAO();

                    Hero h = new Hero();

                    String name = tfName.getText();

                    // 通过name长度判断 名称是否为空

                    if (name.length() == 0) {

                        // 弹出对话框提示用户

                        JOptionPane.showMessageDialog(f, "名称不能为空");

                        // 名称输入框获取焦点

                        tfName.grabFocus();

                        return;

                    }

                    String hp = tfHp.getText().trim();

                    try {

                        // 把hp转换为浮点型,如果出现异常NumberFormatException表示不是浮点型格式

                        Float.parseFloat(hp);

                    catch (NumberFormatException e1) {

                        JOptionPane.showMessageDialog(f, "血量只能是小数 ");

                        tfHp.grabFocus();

                        return;

                    }

                    h.name = name;

                    h.hp = Float.parseFloat(hp);

                    dao.add(h);

                    htm.heros = dao.list();

                    t.updateUI();

                }

            });

            JScrollPane sp = new JScrollPane(t);

            f.add(p, BorderLayout.NORTH);

            f.add(sp, BorderLayout.CENTER);

            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            f.setVisible(true);

        }

    }

    示例 10 : 选中指定行

    1. table初始化后,应该默认选中第一行 
    2. 增加数据后,也应该选中新增的这一条

    选中指定行

    package gui;

    import java.awt.BorderLayout;

    import java.awt.Dimension;

    import java.awt.event.ActionEvent;

    import java.awt.event.ActionListener;

    import javax.swing.JButton;

    import javax.swing.JFrame;

    import javax.swing.JLabel;

    import javax.swing.JOptionPane;

    import javax.swing.JPanel;

    import javax.swing.JScrollPane;

    import javax.swing.JTable;

    import javax.swing.JTextField;

    import javax.swing.ListSelectionModel;

    import jdbc.HeroDAO;

    import charactor.Hero;

    public class TestGUI {

        public static void main(String[] args) {

            final JFrame f = new JFrame("LoL");

            f.setSize(400300);

            f.setLocation(200200);

            f.setLayout(new BorderLayout());

            final HeroTableModel htm = new HeroTableModel();

            final JTable t = new JTable(htm);

            // 设置选择模式为 只能选中一行

            t.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

            // 选中第一行 (基本0)

            t.getSelectionModel().setSelectionInterval(00);

            JPanel p = new JPanel();

            final JLabel lName = new JLabel("名称");

            final JTextField tfName = new JTextField("");

            final JLabel lHp = new JLabel("血量");

            final JTextField tfHp = new JTextField("");

            JButton bAdd = new JButton("增加");

            tfName.setPreferredSize(new Dimension(8030));

            tfHp.setPreferredSize(new Dimension(8030));

            p.add(lName);

            p.add(tfName);

            p.add(lHp);

            p.add(tfHp);

            p.add(bAdd);

            bAdd.addActionListener(new ActionListener() {

                @Override

                public void actionPerformed(ActionEvent e) {

                    HeroDAO dao = new HeroDAO();

                    Hero h = new Hero();

                    String name = tfName.getText();

                    if (name.length() == 0) {

                        JOptionPane.showMessageDialog(f, "名称不能为空");

                        tfName.grabFocus();

                        return;

                    }

                    String hp = tfHp.getText().trim();

                    try {

                        Float.parseFloat(hp);

                    catch (NumberFormatException e1) {

                        JOptionPane.showMessageDialog(f, "血量只能是小数 ");

                        tfHp.grabFocus();

                        return;

                    }

                    h.name = name;

                    h.hp = Float.parseFloat(hp);

                    dao.add(h);

                    htm.heros = dao.list();

                    t.updateUI();

                    // 选中 第一行 ,因为 DAO是按照 ID倒排序查询,所以第一行就是新加入的数据

                    t.getSelectionModel().setSelectionInterval(00);

                }

            });

            JScrollPane sp = new JScrollPane(t);

            f.add(p, BorderLayout.NORTH);

            f.add(sp, BorderLayout.CENTER);

            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            f.setVisible(true);

        }

    }


    更多内容,点击了解: https://how2j.cn/k/gui/gui-table/410.html

  • 相关阅读:
    VMware15 安装centos7标准板
    jQuery拼接HTML标签元素
    解决win10 蓝牙设备只能配对无法连接 ,并且删除设备无效的问题
    Linux:系统的基本优化
    nano编辑器的设置
    Linux:网络yum源设置
    MySQL:MySQL的基本操作
    MySQL:MySQL的安装
    Python之路:堡垒机实例以及数据库操作
    paramiko 模块安装
  • 原文地址:https://www.cnblogs.com/Lanht/p/12615447.html
Copyright © 2011-2022 走看看