我有一个带有 JPanel 的 JSrollPane 作为 ViewPort 组件。在这个 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);
}
}
}
}
编辑:在我对问题的回答中,此代码的更新/固定版本如下。