• 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看起来不一致等。

    积极的人,象太阳,照到哪里哪里亮,消极的人,象月亮,初一十五不一样。想法决定我们的生活,有什么样的想法,就有什么样的未来。对于刚刚进入职场的我们,会经历很多不同的心境变化,很多时候现实跟你想象的都大相庭径,良好的心态很重要!
  • 相关阅读:
    C#
    C#
    ssh学习笔记
    (已解决)Could not open '/var/lib/nova/mnt/*/volume-*': Permission denied
    RPCVersionCapError: Requested message version, 4.17 is incompatible. It needs to be equal in major version and less than or equal in minor version as the specified version cap 4.11.
    如何在linux下安装idea
    The system has no LUN copy license
    调整mysql数据库最大连接数
    mysql数据库编码问题
    cinder支持nfs快照
  • 原文地址:https://www.cnblogs.com/wuxinyu/p/3040218.html
Copyright © 2020-2023  润新知