用JTable实现Excel冻结列效果

本文介绍了一种在Java Swing中实现表格冻结表头的方法,通过使用两个JTable和JScrollPane来确保部分表头始终保持可见,即便在滚动查看长表格数据时也是如此。此外,还提供了同步选择和鼠标事件的技术细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
具体思路:
1.    我们可以考虑使用两个JTablefixTablemainTable
2.    定义一个JScrollPane,mainTable放在他的viewPort中,
3.    在新new一个JViewport,把fixTable放在他的上面
4.    利用JScrollPanesetRowHeaderView()方法,把这个JViewport作为他的RowHeader
5.    最后把fixTable tableHeader放在JScrollPane的左上方(利用setCorner方法
6.    实现选中的同步,因为是2table,所以我们要人工实现他的同步,使用户开着好象一个table.
7.    有的时候我们可能还要在表格上监听鼠标事件,那么这个我们如何同步呢,我的想法是我们增加鼠标事件时只给mainTable添加,而fixTable的鼠标事件默认调用mainTable的处理方法,从而实现事件的传递。
好了下面我们来看一下代码:
首先是我封装好的FixTable
(1)   import java.awt.event.MouseAdapter;
(2)   import java.awt.event.MouseEvent;
(3)   import java.awt.event.MouseListener;
(4)    
(5)   import javax.swing.JScrollPane;
(6)   import javax.swing.JTable;
(7)   import javax.swing.JViewport;
(8)   import javax.swing.ListSelectionModel;
(9)   import javax.swing.event.ListSelectionEvent;
(10) import javax.swing.event.ListSelectionListener;
(11) import javax.swing.table.AbstractTableModel;
(12)  
(13) publicclass FixTable {
(14)  private JTable mainTable;
(15)  private JTable fixTable;
(16)  private FixTableModel fixModel;
(17)  private MainTableModel mainModel;
(18)  privateintfixColumnCount; // 冻结的列数
(19)  private String[] columnHeader; // 表头
(20)  private JScrollPane mainScroll;// 装载在父Container的组件
(21)  
(22)  // private Vector tableData = new Vector(); // 表格中数据
(23)  private Object[][] tableData;
(24)  
(25)  public FixTable(int fixColumnCount, String[] columnHeader,
(26)          Object[][] tableData) {
(27)      this.fixColumnCount = fixColumnCount;
(28)      this.columnHeader = columnHeader;
(29)      this.tableData = tableData;//
(30)      this.initComponents();
(31)  }
(32)  
(33)  /**
(34)   *初始化界面
(35)   */
(36)  privatevoid initComponents() {
(37)      mainTable = new JTable();
(38)      fixTable = new JTable();
(39)      mainModel = new MainTableModel();
(40)      fixModel = new FixTableModel();
(41)      mainTable.setModel(mainModel);
(42)      mainTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
(43)      mainTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
(44)      fixTable.setModel(fixModel);
(45)      fixTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
(46)      fixTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
(47)  
(48)      mainTable.getSelectionModel().addListSelectionListener(
(49)             new ListSelectionListener() {
(50)  
(51)                 @Override
(52)                 publicvoid valueChanged(ListSelectionEvent e) {
(53)                    // TODO Auto-generated method stub
(54)                    checkSelection(false);
(55)                 }
(56)  
(57)             });
(58)      fixTable.getSelectionModel().addListSelectionListener(
(59)             new ListSelectionListener() {
(60)                 @Override
(61)                 publicvoid valueChanged(ListSelectionEvent e) {
(62)                    // TODO Auto-generated method stub
(63)                    checkSelection(true);
(64)                 }
(65)             });
(66)  
(67)      // 添加鼠标事件同步两个表的鼠标双击事件
(68)      mainTable.addMouseListener(new MouseAdapter() {
(69)          publicvoid mouseClicked(MouseEvent e) {
(70)             if (e.getClickCount() > 1) {
(71)                 if (e.getSource().equals(mainTable)) {
(72)                    MouseListener[] mls = (MouseListener[]) fixTable
(73)                           .getListeners(MouseListener.class);
(74)                    for (int i = 0; i < mls.length; i++)
(75)                        mls[i].mouseClicked(e);
(76)                 }
(77)  
(78)             }
(79)          }
(80)      });
(81)  
(82)      fixTable.addMouseListener(new MouseAdapter() {
(83)          publicvoid mouseClicked(MouseEvent e) {
(84)             if (e.getClickCount() > 1) {
(85)                 if (e.getSource().equals(fixTable)) {
(86)                    System.out.println("首先点击了冻结列");
(87)                 } else {
(88)                    System.out.println("首先点击了内容列");
(89)                 }
(90)                 // if (e.getSource().equals(fixTable)) {
(91)                 // MouseListener[] mls = (MouseListener[]) mainTable
(92)                 // .getListeners(MouseListener.class);
(93)                 // for (int i = 0; i < mls.length; i++)
(94)                 // mls[i].mouseClicked(e);
(95)                 // }
(96)             }
(97)          }
(98)      });
(99)  
(100)        mainScroll = new JScrollPane();
(101)        mainScroll.getViewport().add(mainTable);
(102)  
(103)        JViewport fixPort = new JViewport();
(104)        fixPort.setPreferredSize(fixTable.getPreferredSize());
(105)        fixPort.add(fixTable);
(106)        mainScroll.setRowHeaderView(fixPort);
(107)        mainScroll.setCorner(JScrollPane.UPPER_LEFT_CORNER, fixTable
(108)               .getTableHeader());
(109)     }
(110)  
(111)     /**
(112)      *在表格中放入数据
(113)      *
(114)      *@paramtableData
(115)      */
(116)     publicvoid setData(Object[][] tableData) {
(117)        this.tableData = tableData;
(118)     }
(119)  
(120)     /**
(121)      *返回冻结表格的内容面板使用panel.add(table.getTableContentPane());才能使表格加到容器中
(122)      *
(123)      *@return
(124)      */
(125)     public JScrollPane getTableContentPane() {
(126)        returnmainScroll;
(127)     }
(128)  
(129)     /**
(130)      *使两个table同时响应选中事件
(131)      *
(132)      *@paramisFixedTable
(133)      */
(134)     privatevoid checkSelection(boolean isFixedTable) {
(135)        int fixedSelectedIndex = fixTable.getSelectedRow();
(136)        int selectedIndex = mainTable.getSelectedRow();
(137)        if (fixedSelectedIndex != selectedIndex) {
(138)            if (isFixedTable) {
(139)               mainTable.setRowSelectionInterval(fixedSelectedIndex,
(140)                      fixedSelectedIndex);
(141)            } else {
(142)               fixTable.setRowSelectionInterval(selectedIndex, selectedIndex);
(143)            }
(144)        }
(145)  
(146)     }
(147)  
(148)     /**
(149)      *冻结的列表模型
(150)      *
(151)      *@authorbenson
(152)      *
(153)      */
(154)     privateclass FixTableModel extends AbstractTableModel {
(155)  
(156)        @Override
(157)        publicint getColumnCount() {
(158)            // TODO Auto-generated method stub
(159)            returnfixColumnCount;
(160)        }
(161)  
(162)        @Override
(163)        publicint getRowCount() {
(164)            // TODO Auto-generated method stub
(165)            returntableData.length;
(166)        }
(167)  
(168)        @Override
(169)        public Object getValueAt(int rowIndex, int columnIndex) {
(170)            // TODO Auto-generated method stub
(171)            if (tableData[rowIndex][columnIndex] != null)
(172)               returntableData[rowIndex][columnIndex];
(173)            return"";
(174)        }
(175)  
(176)        public String getColumnName(int column) {
(177)            returncolumnHeader[column];
(178)        }
(179)     }
(180)  
(181)     /**
(182)      *数据列表模型
(183)      *
(184)      *@authorbenson
(185)      *
(186)      */
(187)     privateclass MainTableModel extends AbstractTableModel {
(188)  
(189)        @Override
(190)        publicint getColumnCount() {
(191)            // TODO Auto-generated method stub
(192)            returncolumnHeader.length - fixColumnCount;
(193)        }
(194)  
(195)        @Override
(196)        publicint getRowCount() {
(197)            // TODO Auto-generated method stub
(198)            returntableData.length;
(199)        }
(200)  
(201)        @Override
(202)        public Object getValueAt(int rowIndex, int columnIndex) {
(203)            // TODO Auto-generated method stub
(204)            if (tableData[rowIndex][columnIndex + fixColumnCount] != null)
(205)               returntableData[rowIndex][columnIndex + fixColumnCount];
(206)            return"";
(207)        }
(208)  
(209)        public String getColumnName(int column) {
(210)            returncolumnHeader[column + fixColumnCount];
(211)        }
(212)  
(213)     }
(214) }
 
测试主函数
 
import java.awt.BorderLayout;
import java.awt.Dimension;
 
import javax.swing.JFrame;
import javax.swing.JPanel;
 
publicclass FixTableFrame extends JFrame {
 
    private FixTable table;
 
    /**
     *Launchtheapplication
     *
     *@paramargs
     */
    publicstaticvoid main(String args[]) {
       try {
           FixTableFrame frame = new FixTableFrame();
           frame.setVisible(true);
           frame.pack();
       } catch (Exception e) {
           e.printStackTrace();
       }
    }
 
    /**
     *Createtheframe
     */
    public FixTableFrame() {
       super("冻结表头");
       this.setPreferredSize(new Dimension(300, 200));
       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
       final JPanel panel = new JPanel();
       panel.setLayout(new BorderLayout());
       getContentPane().add(panel, BorderLayout.CENTER);
 
       String[] columns = new String[] { "姓名", "学号", "英语", "语文", "数学", "综合" };
 
       Object[][] data = new Object[][] {
              { "Benson", "1", "84", "74", "65", "76" },
              { "Jim", "2", "63", "77", "88", "99" },
              { "King", "3", "78", "76", "56", "98" },
              { "Laura", "4", "98", "76", "87", "66" },
              { "Fisher", "5", "76", "46", "86", "45" },
              { "Mike", "6", "54", "78", "67", "44" } };
       table = new FixTable(1, columns, data);
       // table.setData(data);
       // 此方法一定调用
        // 不能用panel.add(table);因为table已经不是一个Component而是一个合成组件
       panel.add(table.getTableContentPane());
    }
 
}
 
结束语:当然这个表格功能还不完善,还需要添加刷新,增加,删除等功能,实现起来并不复杂,那就大家自己来实现吧。
 
效果图:
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值