Mam JSrollPane z JPanel jako składnik ViewPort. Na tym JPanelu używam paintComponent do narysowania siatki o kwadratach 64x64px. JPanel jest dość duży, 28'672px na 14'336px, nadal siatka jest rysowana od razu i wszystko wydaje się w porządku. Problem polega na tym, że przewijanie w pionie lub w poziomie powoduje, że użycie procesora przeskakuje dość wysoko, im szybciej przewijam, tym wyżej. Wykorzystanie procesora wzrasta do 35-50% podczas przewijania. Przewijanie JPanela o tym samym rozmiarze bez narysowanej siatki, zużywa bardzo mało CPU, więc siatka jest z pewnością przyczyną problemu. Ta siatka jest najbardziej podstawową częścią tego, co planuję zrobić wewnątrz scrollpane, jeśli działa teraz źle, obawiam się, że nie będzie można jej użyć po dodaniu więcej "zawartości".JPanel z siatką namalowaną na nim, powodującą wysokie użycie procesora podczas przewijania
Moje pytanie (y) Dlaczego do przewijania tej siatki zużywa się tak dużo procesora, czy siatka jest odświeżana za każdym razem, gdy następuje zmiana położenia suwaka? Czy istnieje lepszy lub bardziej skuteczny sposób narysowania przewijanej siatki?
Wpadłem na pomysł, że rysuję tylko siatkę widocznego obszaru (przez współrzędne), a następnie przerysowuję ten widoczny obszar, gdy paski przewijania są przesuwane, ale to wywoływałoby odświeżanie. Jeśli to możliwe, chciałbym narysować całą siatkę przy starcie, a następnie tylko odświeżyć na polecenie.
Oto prosty przykład działania mojej siatki 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);
}
}
}
}
EDIT: Zaktualizowana/wersja ustalona tego kodu jest poniżej, w mojej odpowiedzi na pytanie.
Ty rzeczywiście przetwarzanie i malowanie na 28672 x 14336 powierzchni. Możesz zmniejszyć go tylko do widocznego klipu. – tenorsax