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

标签 java swing jtable renderer

快速场景......

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 列。

单击第 30 栏列标题,然后快速将其一直向左和一直向右移动,您会发现它移动得非常快。

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

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

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

请注意,这次柱子的移动存在巨大的滞后。

我确实尝试在移动列标题时设置一个 boolean 值以防止渲染器执行,但它仍然涉及并且似乎并没有真正的帮助。

问题:

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

由于列渲染器多种多样且字段数量众多,是否有更有效的方法来实现渲染器?

最佳答案

is there a more efficient way to implement renderers?

扩展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 了解有关效率的更多信息。

关于java - 使用大量列时的 JTable 渲染器性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68168430/

相关文章:

java - 如何从java上的json列表中获取选定的值

java - 如何创建多层JComboBox

java - 重绘和 SwingUtilities.updateComponentTreeUI 有什么区别?

java - swing创建自定义Jbutton问题

Java:通过单击表单的其他空间来清除 JTable 中的选择

java - 无法为 JTable 提供首选大小

java - 从HIVE表中复制副本,需要写出删除的记录并获取计数

java - 使用spark和java在cassandra中保存对象

java - 将 Swagger Basic AUTH 添加到 Spring Boot 应用程序

java - 树表 : links are not shown