---
title: Swingコンポーネントの再描画をJXLayerのDebugPainterを使ってデバッグ
author: aterai
pubdate: 2008-06-05
description: JXLayerのDebugPainterを使用したコンポーネントの再描画を可視化するjavaagentでデバッグを行います。
---
#contents
* Summary [#summary]
`JXLayer`の`DebugPainter`を使用したコンポーネントの再描画を可視化する`javaagent`でデバッグを行います。
- [https://ateraimemo.com/data/swing/debugpainter.jar debugpainter.jar]
- [https://ateraimemo.com/data/swing/debugpainter_src.zip debugpainter_src.zip]
#ref(https://lh4.googleusercontent.com/_9Z4BYR88imo/TUFGtJHiIaI/AAAAAAAAAzs/ye6so-pxydw/s800/DebugPainterAgent.png)
* ソースコード [#sourcecode]
#code{{
package org.jdesktop.swinghelper.layer.demo;
import java.awt.*;
import java.lang.instrument.*;
import javax.swing.*;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.ext.DebugRepaintingUI;
public class DebugPainterAgent {
public static void premain(String args) throws Exception {
//System.out.println("premain");
agentmain(args);
}
public static void agentmain(String args) throws Exception {
System.out.println("agentmain start");
new Thread() {
@Override public void run() {
System.out.println("Thread run");
Frame[] list = Frame.getFrames();
while (list.length==0) { //FIX ME!
try {
sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.print(".");
list = Frame.getFrames();
}
System.out.println(" ");
System.out.println("Loop out");
replaceLayer();
System.out.println("Thread exit");
}
} .start();
System.out.println("agentmain end");
}
private static void replaceLayer() {
for (Frame f:Frame.getFrames()) {
if (f instanceof JFrame) {
final JFrame frame = (JFrame)f;
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
System.out.println("replace layer");
JComponent c = (JComponent)frame.getContentPane();
JXLayer<JComponent> layer = new JXLayer<JComponent>(c);
layer.setUI(new DebugRepaintingUI());
frame.setContentPane(layer);
frame.pack();
}
});
}
}
}
}
}}
* Description [#explanation]
* Description [#description]
例えば、`repaint`が無限ループしているバグのあるサンプルを以下のように起動すると、`JLabel`の描画が無駄に繰り返され、`CPU`の使用率も異常になっている様子がすぐに分かります。
//--debugpainter.batをクリックします。
//--このデモに添付している TableCellProgressBar などは、JTableのセルや、ポップアップメニューを開いたときの再描画が分かりやすくて面白いかも。
- [https://java.net/projects/jxlayer Jxlayer — Project Kenai]から`jxlayer.jar`をダウンロードし、カレントもしくは、`.\lib`以下に配置
- [https://ateraimemo.com/data/swing/debugpainter.jar debugpainter.jar]をダウンロードし、カレントディレクトリに配置
-- または、ソース([https://ateraimemo.com/data/swing/debugpainter_src.zip debugpainter_src.zip])をダウンロードし、コンパイルして生成
#code{{
javac RepaintLoopTest.java
java -javaagent:debugpainter.jar RepaintLoopTest
REM java -javaagent:debugpainter.jar -jar example.jar
}}
#code{{
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class RepaintLoopTest {
public JComponent makeUI() {
String[] columnNames = {"String", "Integer", "Boolean"};
Object[][] data = {
{"aaa", 12, true}, {"bbb", 5, false},
{"CCC", 92, true}, {"DDD", 0, false}
};
DefaultTableModel model = new DefaultTableModel(data, columnNames) {
@Override public Class<?> getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};
JTable table = new JTable(model);
table.setAutoCreateRowSorter(true);
JLabel label = new JLabel("aaaaaaaaa") {
int h = 10;
int d = 1;
@Override protected void paintComponent(Graphics g) {
super.paintComponent(g);
repaint(); //BUG: an infinite repaint loop
}
};
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table));
p.add(label, BorderLayout.SOUTH);
p.setPreferredSize(new Dimension(320, 240));
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new RepaintLoopTest().makeUI());
f.pack(); //setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
}}
* Reference [#reference]
- %%[https://jxlayer.dev.java.net/ jxlayer: Project Home Page]%%
- %%[https://java.net/projects/jxlayer Jxlayer — Project Kenai]%%
- %%[http://weblogs.java.net/blog/alexfromsun/archive/2007/11/debug_swing_rep.html Alexander Potochkin's Blog: Debug Swing repainting]%%
- %%[http://weblogs.java.net/blog/alexfromsun/archive/2008/06/the_new_jxlayer.html Alexander Potochkin's Blog: JXLayer 3.0 - Getting started]%%
- [[DebugGraphicsを使用してJComponentの描画をデバッグする>Swing/DebugGraphics]]
-- `DebugGraphicsOptions`を設定してコンポーネントの描画を逐次遅延してデバックする
- [http://www.java2s.com/Tutorial/Java/0240__Swing/DebugGraphics.htm DebugGraphics : DebugGraphics « Swing « Java Tutorial]
* Comment [#comment]
#comment
#comment