Reputation: 171
I wrote a simple 2D game - Sokoban (http://www.game-sokoban.com/). I have a two-dimensional field on the screen. Separate JPanel Board is responsible for it.
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.io.IOException;
import java.util.Properties;
public class Board extends JPanel {
private static final String CONFIG_FILE_NAME = "ImageConfig.txt";
/** length px of a square cell */
private static final int SPACE = 20;
private Properties properties;
private Map<Status, Image> Images = null;
private Status[][] cells = null;
private BufferedImage canvas = null;
private Graphics2D g2d = null;
public Board() {
Properties properties = new Properties();
try {
//load a properties file
properties.load(ClassLoader.getSystemResourceAsStream(CONFIG_FILE_NAME));
}
catch (IOException ex) {
ex.printStackTrace();
}
Images = new HashMap<Status, Image>();
for (String key : properties.stringPropertyNames()) {
switch (key) {
case "AREA" : {
Images.put(Status.AREA, null);
break;
}
case "BAGGAGE" : {
Images.put(Status.BAGGAGE, null);
break;
}
case "FREE" : {
Images.put(Status.FREE, null);
break;
}
case "SOKO" : {
Images.put(Status.SOKO, null);
break;
}
case "WALL" : {
Images.put(Status.WALL, null);
break;
}
}
}
this.properties = properties;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(this.canvas, cells.length, cells[0].length, this);
}
public void setSize_(int height, int width) {
canvas = new BufferedImage(width * SPACE, height * SPACE, BufferedImage.TYPE_INT_RGB);
g2d = canvas.createGraphics();
setPreferredSize(new Dimension(width * SPACE, height * SPACE));
cells = new Status[height][width];
}
public void drawCell(int i, int j, Status status) {
cells[i][j] = status;
try {
g2d.drawImage(getImage(cells[i][j]), j * SPACE, i * SPACE, this);
}
catch (Exception e) {
e.printStackTrace();
}
repaint();
}
}
At each move the player on the field is updated, only two or three cells. I want not to redraw all field, and to call only some calls of drawImage (...) on g2d and that changes were right there displayed on the screen. As to me to implement it (without paintComponent())?
Upvotes: 1
Views: 175
Reputation: 21233
You can utilize clipping to speed up painting process. You can set clip using setClip()
method. Also, there is an overloaded version of repaint()
that takes arguments to define only the region that requires updating. Swing sets the clip for you whenever you call repaint(x, y, width,height)
. Then inside paintComponent()
you can choose to honor the clip. You can get it from Graphics
with getClipBounds()
method. And paint only the required area.
Take a look at Painting in AWT and Swing for more details and examples. Also see Performing Custom Painting tutorial, there is an example that illustrates clipped painting.
Upvotes: 3
Reputation: 109613
Use something like:
Rectangle rect = new Rectangle(i * SPACE, j * SPACE, SPACE, SPACE);
repaint(50L, rect);
The delay in ms, 50, is nice to the repainting process. Not sure about i,j or j,i.
Upvotes: 1