用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)  public class FixTable {
(14)    private JTable mainTable ;
(15)    private JTable fixTable ;
(16)    private FixTableModel fixModel ;
(17)    private MainTableModel mainModel ;
(18)    private int 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)    private void 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)                  public void 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)                  public void valueChanged(ListSelectionEvent e) {
(62)                     // TODO Auto-generated method stub
(63)                     checkSelection( true );
(64)                  }
(65)              });
(66)  
(67)       // 添加鼠标事件同步两个表的鼠标双击事件
(68)       mainTable .addMouseListener( new MouseAdapter() {
(69)           public void 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)           public void 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)      public void 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)      private void 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)      private class FixTableModel extends AbstractTableModel {
(155)  
(156)         @Override
(157)         public int getColumnCount() {
(158)             // TODO Auto-generated method stub
(159)             return fixColumnCount ;
(160)         }
(161)  
(162)         @Override
(163)         public int 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)      private class MainTableModel extends AbstractTableModel {
(188)  
(189)         @Override
(190)         public int getColumnCount() {
(191)             // TODO Auto-generated method stub
(192)             return columnHeader . length - fixColumnCount ;
(193)         }
(194)  
(195)         @Override
(196)         public int 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;
 
public class FixTableFrame extends JFrame {
 
    private FixTable table ;
 
    /**
      * Launch the application
      *
      * @param args
      */
    public static void 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());
    }
 
}
 
结束语:当然这个表格功能还不完善,还需要添加刷新,增加,删除等功能,实现起来并不复杂,那就大家自己来实现吧。
 
效果图:
 
 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值