优化 jtable

Optimizing a jtable

我从 JLabel 中创建了一个 TableCellRenderer,它的 paint() 有点重,主要是因为给定了一个 utf 字符串的 g2d.drawString()。问题是这个 paint() 在以下堆栈中被多次调用:

MultiTableCellRenderer$TableHeaderLabel.paint:235   
CellRendererPane.paintComponent:151 
BasicTableUI.paintCell:2115 
BasicTableUI.paintCells:2016    
BasicTableUI.paint:1812 
ComponentUI.update:161  
JComponent.paintComponent:780   
JComponent.paint:1056   
JComponent.paintChildren:889    
JComponent.paint:1065   
JViewport.paint:728 
JComponent.paintChildren:889    
JComponent.paint:1065   
JComponent.paintChildren:889    
JComponent.paint:1065   
JComponent.paintChildren:889    
JComponent.paint:1065   
JComponent.paintChildren:889    
JSplitPane.paintChildren:1047   
JComponent.paint:1065   
JComponent.paintToOffscreen:5219    
RepaintManager$PaintManager.paintDoubleBuffered:1572    
RepaintManager$PaintManager.paint:1495  
RepaintManager.paint:1265   
JComponent._paintImmediately:5167   
JComponent.paintImmediately:4978    
RepaintManager.run:824    
RepaintManager.run:807    
AccessController.doPrivileged   
....

如何防止这种重复过程?我检查了 DefaultTableCellRenderer 实现,发现它们已经覆盖了很多方法,例如 repaint()revalidate() 等,用空方法替换了大部分方法以提高性能。我也这样做了,它确实有所帮助,但问题的大部分仍然存在。至少我的 CPU 的 10% 被这种非常 paint() 的方法不断消耗,整个应用程序已经严重变慢。有什么想法吗?

要了解为什么会过度调用paint方法,可以从查看DefaultTableCellRenderer JavaDoc开始。
您还需要了解 Swing 绘图机制以及重新验证的工作原理。
您可以阅读 AWT 和 Swing 中的绘画 here

一个简单而高效(性能方面和代码方面)的经验法则是扩展 DefaultTableCellRenderer 并根据您的需要对其进行自定义。
自定义通常通过覆盖 setValue()getTableCellRendererComponent().

来完成

请务必注意 getTableCellRendererComponent():

  1. 通常 returns 对自身的引用。
  2. 应该每次调用时都创建一个新对象,正是出于性能原因。
  3. 作为橡皮图章渲染 所有 个单元格,一次一个。
  4. 使用优化的对象(在 DefaultTableCellRenderer 的情况下修改 JLabel)进行绘制、重新验证和重新绘制。

尝试使用探查器比较您现有的实现和此实现,以说服自己它产生的绘图和布局事件要少得多,而且 CPU 利用率更高。