ViewPort コンポーネントとして JPanel を持つ JSrollPane があります。この JPanel では、paintComponent を使用して 64x64px の正方形のグリッドを描画します。JPanel は 28,672 ピクセル x 14,336 ピクセルと非常に大きく、それでもグリッドは即座に描画され、すべて問題ないように見えます。問題は、縦または横にスクロールすると CPU 使用率が非常に高くなることです。スクロール中に CPU 使用率が最大 35 ~ 50% になります。グリッドを描画せずに同じサイズの JPanel をスクロールすると、CPU の使用量が非常に少なくなるため、グリッドが問題の原因であることは間違いありません。このグリッドは、スクロールペイン内で私が計画していることの最も基本的な部分です。現在パフォーマンスが悪い場合、さらに「コンテンツ」が追加された後に使用できなくなるのではないかと心配しています。
私の質問 このグリッドをスクロールするのに CPU を大量に使用するのはなぜですか? スクロールバーの位置が変わるたびにグリッドが再描画されますか? スクロール可能なグリッドを描画するためのより良い、またはより効率的な方法はありますか?
可視領域のグリッドのみを(座標で)描画し、スクロールバーが移動したときにその可視領域を再描画するという考えがありましたが、これは多くの再描画を呼び出すことになります。可能であれば、起動時にグリッド全体を描画し、コマンドでのみ再描画したいと思います。
これは、私の JPanel グリッドの最低限の作業例です。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.EmptyBorder;
public class GridTest extends JFrame
{
static JScrollPane scrollPane;
static JPanel contentPane,gridPane;
public static void main(String[] args) {
GridTest frame = new GridTest();
frame.setVisible(true);
}
public GridTest(){
setTitle("Grid Test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setBounds(300, 100, 531, 483);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
scrollPane = new JScrollPane();
scrollPane.setBounds(0, 0, 526, 452);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
contentPane.add(scrollPane);
gridPane = new JPanel() {
public void paintComponent( Graphics g ){
super.paintComponent(g);
drawGrid(g);
g.dispose();
}};
Dimension gridPaneSize = new Dimension(28672,14336);
//Dimension gridPaneSize = new Dimension(4096,4096);
gridPane.setBackground(Color.BLACK);
gridPane.setPreferredSize(gridPaneSize);
scrollPane.setViewportView(gridPane);
}
public static void drawGrid(Graphics g)
{
int width = gridPane.getWidth();
int height = gridPane.getHeight();
g.setColor(Color.gray);
// draw horizontal long lines
for(int h = 0; h < height; h+=64){
g.drawLine(0, h, width, h);
}
// draw even grid vert lines
for(int w = 0; w < width; w+=64){
for(int h = 0; h < height; h+=128){
g.drawLine(w, h, w, h+64);
}
}
// draw odd grid vert lines
for(int w = 32; w < width; w+=64){
for(int h = 64; h < height; h+=128){
g.drawLine(w, h, w, h+64);
}
}
}
}
編集:このコードの更新/修正バージョンは、質問に対する私の回答の下にあります。