具体思路:
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) 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());
}
}
结束语:当然这个表格功能还不完善,还需要添加刷新,增加,删除等功能,实现起来并不复杂,那就大家自己来实现吧。
效果图: