• JAVA Swing中JTable的固定列问题


       转自http://tech.ddvip.com/2009-09/1253671352134031.html

    固定JTable中的前几列

    2009-09-23 10:03:57     发表评论

      当很表格中有很多列的时候出现Scrollbar的时候,当用户拖动Scrollbar那么有的列就会看不见,而用户需要输入数据的时 候,需要对照第一列或前几列以方便输入数据,则需要固定前几列的需求了。像Excle表格中可以固定前几列,而在JTable中没有直接的方法实现,网上 比较流行的方法是用两个JTable,如下图(一)其中一个talbe渲染固定列的数据,另外一个主table渲染其他数据,然后把渲染固定列数据的表格 当做装载主table的JScrollPane的Row Header。这样实现就要把表格中的数据拆分成两个TableModel用于其渲染。

      其中实现的效果如图二

      图片看不清楚?请点击这里查看原图(大图)。

      图一

      图二                                                     

      很显然这种实现方式有一下缺点:

      1)、当用户对于自己的表格有自己实现的自定义的列头,比如行的序列号或增加了选择框等等这样就会有冲突。

      2)、如上所说当拆分成两个TableModel的时候,那么要很好的维护两个表格一些属性保持一致将很麻烦,比如选择,排序等。

      3)、最重要的一点就是如果在其原有的项目中增加这一需求,那么这种方法就要修改很多地方,侵入性太强。

       基于上述缺点,Elie Levy 用了另外一种方法,尽管也有些缺点(暂且后面再说),他实现的方法很简单(效果如图三),就是将要固定的列的内容画在一个另外一个组件上然后将 这个组件放在JTable之上,其总是占据其表格的指定需要固定的列上,这表格的前几列看起来就是固定了的,如图三,我们需要固定前三列,那么我们将前三 列的内容画在一个Label上如图中黑色部分,这时候的关键技术就是利用JLayeredPane的原理了,获得JTable的 JLayeredPane,然后将这个画出所要固定列的内容的JLabel加进JLayeredPane,就能忽悠成固定了。

      图片看不清楚?请点击这里查看原图(大图)。

      图三

      主要实现代码分析,实现主要监听鼠标事件,捕捉所要固定的列的内容予以即时更新,这个类FixTableManager为了方便我们继承于JTableHeader,那么在这里我们重写paint()方法:以更新拖动Scrollbar的时候列头的现实信息,代码如:

    双击代码全选
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    @Override
    public void paint(Graphics g) {
     super.paint(g);
     //int division = mouseListener.getDivision();
     int division = mouseListener.getDivision();
     if (division > 0){
      Rectangle r = getVisibleRect();
      BufferedImage image = new BufferedImage(division, r.height,
        BufferedImage.TYPE_INT_ARGB);
      Graphics g2 = image.getGraphics();
      g2.setClip(0, 0, division, r.height);
      g2.setColor(Color.WHITE);
      g2.fillRect(0, 0, division, r.height);
      super.paint(g2);
      g.drawImage(image, r.x, r.y, division, r.height, null);
      g2.dispose();
     }
    }

      画完了固定的列的列头,我们就要画表格中的内容了,这里我们就是把这些内容画在一个JLabel上,如下:

    双击代码全选
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     private class FixedColumnsDelegate extends JLabel{
      public void paintComponent(Graphics g) {
       Rectangle r = table.getBounds();
       if (division > 0) {
        table.invalidate();
        table.validate();
        Rectangle visibleRect = table.getVisibleRect();
        BufferedImage image = new BufferedImage(division, r.height,
          BufferedImage.TYPE_INT_ARGB);
        Graphics g2 = image.getGraphics();
        g2.setClip(0, visibleRect.y, division,
          table.getBounds().height);
        
        g2.setColor(Color.RED);
        g2.fillRect(0, 0, division, table.getBounds().height);
        
        table.paint(g2);
        g.drawImage(image, 0, 0, division,
          table.getBounds().height, 0, visibleRect.y,
          division, visibleRect.y + table.getBounds().height,
          null);
    //    g.setColor(Color.BLACK);
    //    for (int i = 0; i < visibleRect.y
    //      + table.getBounds().height; i += 8) {
    //     g.drawLine(division - 1, i, division - 1, i + 4);
    //     g.drawLine(division - 2, i, division - 2, i + 4);
    //    }
        g2.dispose();
       }
      }
     }

      接下来就是鼠标等一些事件来监听画出固定列的信息了。当捕捉到需要将固定的列固定住,就调用如下方法:

    双击代码全选
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    /** *//**
      *固定列
      *利用JLayeredPane使其显示在JTable之上
      **/
      public void freeze() {
       JLayeredPane pane = table.getRootPane().getLayeredPane();
       if (added) {
        pane.remove(fixedColumns);
       } 
       pane.add(fixedColumns, JLayeredPane.POPUP_LAYER);
       setBoundsOnFrozenColumns();
       added = true;
       fixedColumns.setVisible(true);
      }

      还有一些繁杂的计算ixedColumns的位置大小大家可以下载代码自己看了,大致原理就是如此简单,就是利用JLayeredPane层的概念,用起来也很方便,只需要在原有的代码传入JTable,以及装在这个JTable的JScrollPane,如

    双击代码全选
    1
    2
    3
    4
    5
    JTable table = new JTable(data, columnNames);
     JScrollPane scrollPane = new JScrollPane(table);
     FixTableManager tableHeader = new FixTableManager(table,scrollPane);
     //固定前三列
     tableHeader.setFixCol(2);

       总之这样能忽悠成看起来像是固定了,那它也有感觉不带劲的地方,大家如有兴趣,可以在下面的链接中下载代码,运行其看看效果  ,效果是Scrollbar不会的最小值停留的位置不是在固定列的最后位置,随之scrollbar的拖动,我们可以看到有的列会被固定的列挡住,正如前 面所说,这个所谓的固定是个假象。还有一些缺点如有的皮肤可能算出来的结果会和原有的Table看起来不一致等。

    积极的人,象太阳,照到哪里哪里亮,消极的人,象月亮,初一十五不一样。想法决定我们的生活,有什么样的想法,就有什么样的未来。对于刚刚进入职场的我们,会经历很多不同的心境变化,很多时候现实跟你想象的都大相庭径,良好的心态很重要!
  • 相关阅读:
    meta标签设置(移动端)
    清除浮动
    响应式设计
    堆和堆排序
    O(n^2)以及O(nlogn)时间复杂度的排序算法
    求数组的最大连续子数组和
    HTTP缓存原理
    将两个有序数组合并为一个有序数组
    如何实现居中对齐
    查找字符串中出现最多的字符
  • 原文地址:https://www.cnblogs.com/wuxinyu/p/3040218.html
Copyright © 2020-2023  润新知