Tips/DebugPainterAgent のバックアップ(No.2)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Tips/DebugPainterAgent へ行く。
- 1 (2011-01-27 (木) 19:22:18)
- 2 (2011-02-15 (火) 19:09:24)
- 3 (2013-10-16 (水) 14:29:30)
- 4 (2013-10-31 (木) 16:55:50)
- 5 (2014-08-30 (土) 02:27:55)
- 6 (2014-09-03 (水) 18:12:02)
- 7 (2014-11-08 (土) 01:41:12)
- 8 (2015-09-29 (火) 19:31:35)
- 9 (2016-01-29 (金) 14:01:03)
- 10 (2017-10-27 (金) 16:26:13)
- 11 (2018-02-21 (水) 13:07:34)
- 12 (2018-05-30 (水) 20:58:01)
- 13 (2023-02-20 (月) 01:32:52)
TITLE:Swingコンポーネントの再描画をJXLayerのDebugPainterを使ってデバッグ
Posted by aterai at 2008-06-05
Swingコンポーネントの再描画をJXLayerのDebugPainterを使ってデバッグ
#adsense2
概要
JXLayer のDebugPainter を使ってコンポーネントの再描画を可視化する javaagent を作成してデバッグを行います。
ソースコード
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() {
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() {
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();
}
});
}
}
}
}
解説
例えば、repaintが無限ループしているバグのあるサンプルを以下のように起動すると、JLabelの描画が無駄に繰り返され、CPUの使用率も異常になっている様子がすぐに分かります。
- https://jxlayer.dev.java.net/ から jxlayer.jar をdownloadし、カレントもしくは、.\lib以下に配置
- debugpainter.jar をdownloadし、カレントディレクトリに配置
- または、debugpainter_src.zipから生成
javac RepaintLoopTest.java
java -javaagent:debugpainter.jar RepaintLoopTest
REM java -javaagent:debugpainter.jar -jar example.jar
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 public void paintComponent(Graphics g) {
super.paintComponent(g);
repaint();
}
};
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);
}
}
参考リンク
- jxlayer: Project Home Page
- Alexander Potochkin's Blog: Debug Swing repainting
- Alexander Potochkin's Blog: JXLayer 3.0 - Getting started