I have a JSrollPane with JPanel as a component of ViewPort. In this JPanel, I use paintComponent to draw a 64x64px square grid. JPanel is quite large, 28'672px at 14'336px, and yet the grid is drawn instantly and everything seems beautiful. The problem is that scrolling vertically or horizontally causes the CPU usage to increase very much, the faster I scroll higher. When scrolling, the processor load increases to 35-50%. Scrolling through a JPanel of the same size without a grid drawn on it uses a very small processor, so the grid is certainly the cause of the problem. This grid is the most basic part of what I plan to do inside scrollpane, if it works poorly now, I am afraid that it will be unusable after adding more content.
My question is Why does he use so much CPU to scroll this grid, is the grid redrawn every time the scroll bar is moved? Is there a better or more efficient way to draw a scrollable mesh?
I had the idea of only drawing the grid of the visible area (by coordinate), and then redrawing this visible area while moving the scroll bars, but this will cause the alot to redraw. If possible, I would like to draw the entire grid at startup, and then only redraw on command.
Here is an example of how my JPanel mesh works on barebones.
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);
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);
for(int h = 0; h < height; h+=64){
g.drawLine(0, h, width, h);
}
for(int w = 0; w < width; w+=64){
for(int h = 0; h < height; h+=128){
g.drawLine(w, h, w, h+64);
}
}
for(int w = 32; w < width; w+=64){
for(int h = 64; h < height; h+=128){
g.drawLine(w, h, w, h+64);
}
}
}
}
EDIT: An updated / fixed version of this code is given below in my answer to the question.