用JTable实现Excel冻结列效果

 
具体思路:
1.    我们可以考虑使用两个 JTable fixTable mainTable
2.    定义一个 JScrollPane, mainTable 放在他的 viewPort 中,
3.    在新 new 一个 JViewport ,把 fixTable 放在他的上面
4.    利用 JScrollPane setRowHeaderView ()方法,把这个 JViewport 作为他的 RowHeader
5.    最后把 fixTable tableHeader 放在 JScrollPane 的左上方(利用 setCorner方法
6.    实现选中的同步,因为是 2 table, 所以我们要人工实现他的同步,使用户开着好象一个 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)    privateint fixColumnCount ; // 冻结的列数
(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)        * @param tableData
(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)         return mainScroll ;
(127)      }
(128)  
(129)      /**
(130)        * 使两个 table 同时响应选中事件
(131)        *
(132)        * @param isFixedTable
(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)        * @author benson
(152)        *
(153)        */
(154)      privateclass FixTableModel extends AbstractTableModel {
(155)  
(156)         @Override
(157)         publicint getColumnCount() {
(158)             // TODO Auto-generated method stub
(159)             return fixColumnCount ;
(160)         }
(161)  
(162)         @Override
(163)         publicint getRowCount() {
(164)             // TODO Auto-generated method stub
(165)             return tableData . 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)                return tableData [rowIndex][columnIndex];
(173)             return "" ;
(174)         }
(175)  
(176)         public String getColumnName( int column) {
(177)             return columnHeader [column];
(178)         }
(179)      }
(180)  
(181)      /**
(182)        * 数据列表模型
(183)        *
(184)        * @author benson
(185)        *
(186)        */
(187)      privateclass MainTableModel extends AbstractTableModel {
(188)  
(189)         @Override
(190)         publicint getColumnCount() {
(191)             // TODO Auto-generated method stub
(192)             return columnHeader . length - fixColumnCount ;
(193)         }
(194)  
(195)         @Override
(196)         publicint getRowCount() {
(197)             // TODO Auto-generated method stub
(198)             return tableData . 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)                return tableData [rowIndex][columnIndex + fixColumnCount ];
(206)             return "" ;
(207)         }
(208)  
(209)         public String getColumnName( int column) {
(210)             return columnHeader [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 ;
 
    /**
      * Launch the application
      *
      * @param args
      */
    publicstaticvoid main(String args[]) {
       try {
           FixTableFrame frame = new FixTableFrame();
           frame.setVisible( true );
           frame.pack();
       } catch (Exception e) {
           e.printStackTrace();
       }
    }
 
    /**
      * Create the frame
      */
    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());
    }
 
}
 
结束语:当然这个表格功能还不完善,还需要添加刷新,增加,删除等功能,实现起来并不复杂,那就大家自己来实现吧。
 
效果图:
 
 
 
 
其实滚动面板中还可以放其它面板来实现表格效果
JScrollPane有以下两个方法 setColumnHeaderView(Component view) setRowHeaderView(Component view) 你可以利用它们, 一个用来显示表行头,一个用来显示列头

 主要代码:    其中jpnlMain/jpnlRowHeader/jpnlRowHeader都是面板,注意主面板的PreferredSize大小是行和列所对应的大小.

jslPanel.getViewport().add(jpnlMain);
  JViewport vpColumHeader= new JViewport();
  vpColumHeader.setView(jpnlColumHeader);

 vpColumHeader.setPreferredSize(jpnlRowHeader.getPreferredSize());

  JViewport vpRowHeader= new JViewport();
  vpRowHeader.setView(jpnlRowHeader);
  vpRowHeader.setPreferredSize(jpnlRowHeader.getPreferredSize());

  jslPanel.setColumnHeader(vpColumHeader);
  jslPanel.setRowHeader(vpRowHeader);

 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值