优化 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()
:
- 通常 returns 对自身的引用。
- 应该不每次调用时都创建一个新对象,正是出于性能原因。
- 作为橡皮图章渲染 所有 个单元格,一次一个。
- 使用优化的对象(在 DefaultTableCellRenderer 的情况下修改
JLabel
)进行绘制、重新验证和重新绘制。
尝试使用探查器比较您现有的实现和此实现,以说服自己它产生的绘图和布局事件要少得多,而且 CPU 利用率更高。
我从 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()
:
- 通常 returns 对自身的引用。
- 应该不每次调用时都创建一个新对象,正是出于性能原因。
- 作为橡皮图章渲染 所有 个单元格,一次一个。
- 使用优化的对象(在 DefaultTableCellRenderer 的情况下修改
JLabel
)进行绘制、重新验证和重新绘制。
尝试使用探查器比较您现有的实现和此实现,以说服自己它产生的绘图和布局事件要少得多,而且 CPU 利用率更高。