zoukankan      html  css  js  c++  java
  • Java自学-图形界面 表格

    Swing 使用 JTable详解

    示例 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(400, 300);
            f.setLocation(200, 200);
            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(400, 300);
            f.setLocation(200, 200);
            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(400, 300);
            f.setLocation(200, 200);
            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(400, 300);
            f.setLocation(200, 200);
            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(400, 300);
            f.setLocation(200, 200);
            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为例

    在这里插入图片描述

    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(400, 300);
            f.setLocation(200, 200);
            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(80, 30));
            tfHp.setPreferredSize(new Dimension(80, 30));
     
            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(400, 300);
            f.setLocation(200, 200);
            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(80, 30));
            tfHp.setPreferredSize(new Dimension(80, 30));
     
            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(400, 300);
            f.setLocation(200, 200);
            f.setLayout(new BorderLayout());
     
            final HeroTableModel htm = new HeroTableModel();
     
            final JTable t = new JTable(htm);
            // 设置选择模式为 只能选中一行
            t.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            // 选中第一行 (基本0)
            t.getSelectionModel().setSelectionInterval(0, 0);
     
            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(80, 30));
            tfHp.setPreferredSize(new Dimension(80, 30));
     
            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(0, 0);
                }
            });
     
            JScrollPane sp = new JScrollPane(t);
     
            f.add(p, BorderLayout.NORTH);
            f.add(sp, BorderLayout.CENTER);
     
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
            f.setVisible(true);
        }
    }
    

    更多内容,点击了解: Swing 使用 JTable详解

  • 相关阅读:
    新一代MQ apache pulsar的架构与核心概念
    Flutter使用fluwx实现微信分享
    BZOJ3622 已经没有什么好害怕的了 动态规划 容斥原理 组合数学
    NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分
    Codeforces 555C Case of Chocolate 其他
    NOIP2017提高组Day2T3 列队 洛谷P3960 线段树
    NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp
    NOIP2017提高组Day1T3 逛公园 洛谷P3953 Tarjan 强连通缩点 SPFA 动态规划 最短路 拓扑序
    Codeforces 873F Forbidden Indices 字符串 SAM/(SA+单调栈)
    Codeforces 873E Awards For Contestants ST表
  • 原文地址:https://www.cnblogs.com/jeddzd/p/13549250.html
Copyright © 2011-2022 走看看