微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用大量列时的 JTable 渲染器性能问题

如何解决使用大量列时的 JTable 渲染器性能问题

快速场景.....

JTable 大约有 30 列。在不附加渲染器的情况下,我可以单击第 30 列并将其移动到任何位置,而且速度非常快。没有延迟或任何东西。

由于大多数列都是唯一的,并且需要它们自己的渲染类型,无论是背景颜色、日期格式、字体还是其他,渲染器被分配到特定的列而不是表格。现在发生的情况是,将列移动到不同位置时会出现巨大的滞后。

这是一个基本示例,其中渲染器被注释掉以首先显示它的速度。

import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;

public class LotsOfColumnsWithRenderer
{
    static JFrame f;
    static String data[][];
    static final int colums = 30;
    static final int rows = 100;
    static boolean skipThis = false;
    
      public static void main(String[] argv) throws Exception 
      {
          LotsOfColumnsWithRenderer x = new LotsOfColumnsWithRenderer();
      }

      public LotsOfColumnsWithRenderer()
      {
            f = new JFrame();
            populateData();
            String column[]={"Col 1","Col 2","Col 3","Col 4","Col 5","Col 6","Col 7","Col86","Col 9","Col 10","Col 11","Col 12","Col 13","Col 14","Col 15","Col 16","Col 17","Col 18","Col 19","Col 20","Col 21","Col 22","Col 23","Col 24","Col 25","Col 26","Col 27","Col 28","Col 29","Col 30",};         
        
            JTable table = new JTable(data,column);
            
            //for (int y=0; y < colums; y ++)
            //{
                //table.getColumnModel().getColumn(y).setCellRenderer(new MyTableCellRenderer());
            //}
            
            table.getTableHeader().addMouseListener(new MouseAdapter()
            {
                @Override
                public void mousepressed(MouseEvent e) 
                {
                    if (e.getButton() == MouseEvent.BUTTON1) 
                    {
                        skipThis = true;
                    }
                }

                @Override
                public void mouseReleased(MouseEvent e) 
                {
                    if (e.getButton() == MouseEvent.BUTTON1) 
                    {
                        skipThis = false;
                    }
                }
        
            });

            table.setBounds(30,40,200,300);          
            JScrollPane sp=new JScrollPane(table);    
            f.add(sp);  
            f.setSize(300,400);    
            f.setVisible(true); 
            
            MyTableCellRenderer xx = new MyTableCellRenderer();
            

      }
      

    private static void populateData() 
    {
        data = new String[rows][colums];
        
        for (int x=0; x < rows; x++)
        {
            for (int y=0; y < colums; y ++)
            {
                data[x][y] = "Data for ["+x+"]["+y+"]";
            }
        }
        
    }
    
    public class MyTableCellRenderer extends JLabel implements TableCellRenderer 
    {
        private static final long serialVersionUID = -6320757636864429128L;

        public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int rowIndex,int vColIndex) 
          {
              if (skipThis)
              {
                  System.out.println("Skipping");
                  return this;
              }
              
                setText(value.toString());
                setToolTipText((String) value);
                if (vColIndex == 1)
                    this.setBackground(Color.LIGHT_GRAY);
                else if (vColIndex == 3)
                    this.setBackground(Color.CYAN);
                else if (vColIndex == 7)
                    this.setBackground(Color.YELLOW);
                else if (vColIndex == 20)
                    this.setBackground(Color.GREEN);

                
                this.setopaque(true);
                return this;
          }
    }
}

运行上面的代码

双击 JFrame 顶部以最大化窗口并查看所有 30 列。

点击 Col 30 列标题快速将其一直向左和一直向右移动,注意它的移动速度非常快。

现在取消注释以下代码行。

        //for (int y=0; y < colums; y ++)
        //{
            //table.getColumnModel().getColumn(y).setCellRenderer(new MyTableCellRenderer());
        //}

再次运行应用程序并执行相同的步骤。

注意这次移动列有很大的滞后。

我确实尝试在列标题被移动时设置一个布尔值以防止渲染器执行,但它仍然参与其中并且似乎并没有真正帮助。

问题:

在开始影响性能之前,渲染器的数量是否有限制(或实现渲染器时要遵循的规则)?

由于列渲染器的多样性和大量字段,是否有更有效的方法来实现渲染器?

解决方法

有没有更有效的方法来实现渲染器?

扩展DefaultTableCellRenderer

//public class MyTableCellRenderer extends JLabel implements TableCellRenderer
public class MyTableCellRenderer extends DefaultTableCellRenderer
{
    public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int rowIndex,int vColIndex)
      {
            super.getTableCellRendererComponent(table,value,isSelected,hasFocus,rowIndex,vColIndex);

            //setText(value.toString());
            setToolTipText((String) value);
            if (vColIndex == 1)
                this.setBackground(Color.LIGHT_GRAY);
            else if (vColIndex == 3)
                this.setBackground(Color.CYAN);
            else if (vColIndex == 7)
                this.setBackground(Color.YELLOW);
            else if (vColIndex == 20)
                this.setBackground(Color.GREEN);


            //this.setOpaque(true);
            return this;
      }
}

DefaultTableCellRenderer 覆盖了 JLabel 的各种方法以提高绘制效率,因为它知道组件用作渲染器而不是真正的组件。

例如,当您调用 setText(..) 时,标签不需要 revalidate() 本身。

阅读 DefaultTableCellRenderer API 以了解有关效率的更多信息。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。