如何解决使用大量列时的 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 举报,一经查实,本站将立刻删除。