2017-07-05 4 views
0

Je suis en train de mettre en œuvre la fourmi de Langton, et je l'ai fait bien: langton's ant java simulation screenjava DPanel comment optimiser la peinture

pour la peinture dans mes JPanel, je remplacer les paintComponent à chaque étape, mais il prend beaucoup de temps pour la peinture chaque rectangle noir ou blanc, je veux juste qu'à chaque étape je peins seulement les deux rectangle qui ont changé! Donc, ma question est, comment ne peindre un rectangle sans changer ce qui a été peint dans le cadre précédent?

ici est mon code pour la peinture

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); 
    } 

d'aide? ou devrais-je donner plus de détails? Voici le fichier jar:

Répondre

1

Peignez vos rectangles dans un objet BufferedImage, puis dessinez cette image dans votre méthode paintComponent. Vous pouvez également limiter la quantité de nouveau dessin en utilisant l'un des remplacements repaint(...) qui spécifie la région rectangulaire exacte à repeindre.

Ainsi, votre méthode paintComponent pourrait être aussi simple que cela:

@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); 
} 

Avec les changements de dessin est effectué à l'img BufferedImage.

En supposant que vous utilisez une minuterie Swing pour conduire les changements d'état à votre modèle, vous pourriez

  1. changer le modèle, puis
  2. mise à jour du BufferedImage sur la base des changements de modèle, et
  3. appelez repaint(...) uniquement sur la région mise à jour.

Tentative de code incomplète .... pas encore terminée!

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; 
     } 
    } 
} 
+0

et où devrais-je mettre le dessin de toute la matrice? (Quelque temps où nous redimensionner le jFrame le jPanel doit être redessiné chaque rectangle non? Je veux avoir un problème ici) et je ne peux pas dessiner rectangle au lieu de l'image? –

+0

@NazimeLakehal: voir mise à jour pour répondre –

+0

ok merci, je vais essayer de changer mon code, mais la seule façon de dessiner c'est de surcharger paintComponent? –