我正在尝试实施langton的蚂蚁,我做得很好: langton's ant java simulation screen
在我的jPanel中绘画,我在每一步都覆盖了paintComponent,但是它需要花费很多时间来绘制每个黑色或白色矩形,我只想在每一步我只绘制两个已经改变的矩形!? 所以我的问题是,如何只绘制一个矩形而不改变前一帧中绘制的内容?
这是我的绘画代码
public void paintComponent(Graphics g){
g.setColor(Color.white);
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(Color.black);
int careLargeur = getWidth() / m;
int careHauteur = getHeight() / n;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
if(map[i][j])
g.fillRect(j*careLargeur,i*careHauteur,careLargeur,careHauteur);
}
//draw fourmi
g.setColor(Color.red);
g.fillOval(jF*careLargeur, iF*careHauteur, careLargeur, careHauteur);
}
任何帮助?或者我应该提供更多细节? 这是罐子:
答案 0 :(得分:1)
将矩形绘制到BufferedImage,然后在paintComponent方法中绘制BufferedImage。您还可以使用指定要重新绘制的确切矩形区域的repaint(...)
覆盖之一来限制重绘的数量。
所以你的paintComponent方法可以这么简单:
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
g.setColor(Color.red);
g.fillOval(jF*careLargeur, iF*careHauteur, careLargeur, careHauteur);
}
对img
BufferedImage进行绘图更改。
假设您使用Swing Timer来驱动模型的状态更改,您可以
repaint(...)
。代码尝试不完整......尚未完成!
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;
/**
* https://en.wikipedia.org/wiki/Langton%27s_ant
* https://stackoverflow.com/a/44930371/522444
* @author Pete
*
*/
public class LangtonsAnt {
private static final int TIMER_DELAY = 30;
private static void createAndShowGui() {
Model model = new Model(800);
View view = new View(800);
Controller controller = new Controller(model, view);
JFrame frame = new JFrame("Langtons Ant");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(view);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
controller.startTimer(TIMER_DELAY);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static class Model {
public static final String POINT = "point";
private SwingPropertyChangeSupport support = new SwingPropertyChangeSupport(this);
private int gridSize;
private boolean[][] grid; // false is white. Better to use enums
private Point oldValue;
private Point point; // ant location
public Model(int gridSize) {
this.gridSize = gridSize;
grid = new boolean[gridSize][gridSize];
int x = gridSize / 2;
int y = gridSize / 2;
setPoint(new Point(x, y));
}
public void setPoint(Point point) {
this.oldValue = this.point;
Point newValue = point;
this.point = point;
support.firePropertyChange(POINT, oldValue, newValue);
}
public Point getPoint() {
return point;
}
public boolean[][] getGrid() {
return grid;
}
public int getGridSize() {
return gridSize;
}
public void step() {
// first will hold relative new positions
int newX = 0;
int newY = 0;
boolean gridPoint = getGridPoint(point);
if (oldValue == null) {
newX = point.x;
newY = point.y - 1;
} else {
int dX = point.x - oldValue.x;
int dY = point.y - oldValue.y;
if (dX != 0) {
// from left or right
newY = dX > 0 ? 1 : -1; // assume "white" or false
newY = gridPoint ? -newY : newY; // if "black" then reverse
} else {
// from up or down
newX = dY > 0 ? -1 : 1; // assume "white" or false
newX = gridPoint ? -newX : newX; // if "black" then reverse
}
// convert from relative to absolute new positions
newX = point.x + newX;
newY = point.y + newY;
}
setGridPoint(point, !gridPoint);
setPoint(new Point(newX, newY));
}
public boolean getGridPoint(int x, int y) {
return grid[x][y];
}
public boolean getGridPoint(Point p) {
return getGridPoint(p.x, p.y);
}
public void setGridPoint(int x, int y, boolean b) {
grid[x][y] = b;
}
public void setGridPoint(Point p, boolean b) {
setGridPoint(p.x, p.y, b);
}
public void addPropertyChangeListener(String propertyName, PropertyChangeListener l) {
support.addPropertyChangeListener(propertyName, l);
}
}
private static class Controller {
private Model model;
private View view;
private Timer timer;
public Controller(Model model, View view) {
this.model = model;
this.view = view;
view.setAntImg(createAntImg());
model.addPropertyChangeListener(Model.POINT, new ModelListener());
}
private BufferedImage createAntImg() {
// trivial image for now
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics g = img.getGraphics();
g.setColor(Color.RED);
g.fillRect(0, 0, 1, 1);
g.dispose();
return img;
}
public void startTimer(int delay) {
timer = new Timer(delay, new TimerListener());
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
model.step();
}
}
private class ModelListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
// TODO Finish this.
// get the new point and old point
// translate model coord to view coord
// Change the state of the view's buffered image
// repaint the limited region that was changed
}
}
}
private static class View extends JPanel {
private static final Color BACKGROUND = Color.WHITE;
private BufferedImage gridImg;
private BufferedImage antImg;
private Point guiAntLocation;
private int pixelWidth;
public View(int pixelWidth) {
this.pixelWidth = pixelWidth;
gridImg = new BufferedImage(pixelWidth, pixelWidth, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = gridImg.createGraphics();
g2.setColor(BACKGROUND);
g2.fillRect(0, 0, pixelWidth, pixelWidth);
g2.dispose();
}
public int getPixelWidth() {
return pixelWidth;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (getGridImg() != null) {
g.drawImage(getGridImg(), 0, 0, this);
}
if (guiAntLocation != null && antImg != null) {
int x = guiAntLocation.x;
int y = guiAntLocation.y;
g.drawImage(antImg, x, y, this);
}
}
public void setGuiAntLocation(Point guiAntLocation) {
this.guiAntLocation = guiAntLocation;
}
public Point getGuiAntLocation() {
return guiAntLocation;
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || getGridImg() == null) {
return super.getPreferredSize();
}
return new Dimension(getGridImg().getWidth(), getGridImg().getHeight());
}
public BufferedImage getGridImg() {
return gridImg;
}
public void setGridImg(BufferedImage gridImg) {
this.gridImg = gridImg;
}
public void setAntImg(BufferedImage antImg) {
this.antImg = antImg;
}
}
}