2017-07-05 2 views
0

Ich versuche langton Ameise zu implementieren, und ich habe es gut: langton's ant java simulation screenJava JPanel, wie zur Optimierung der Malerei

für Malerei in meiner JPanel, außer Kraft setzen ich die paintcomponent bei jedem Schritt, aber es so viel Zeit für die Malerei nehmen Jedes schwarze oder weiße Rechteck, ich möchte nur, dass ich bei jedem Schritt nur die zwei Rechtecke male, die sich geändert haben !? Also meine Frage ist, wie man nur ein Rechteck malt, ohne zu ändern, was im vorhergehenden Rahmen gemalt wurde?

hier ist mein Code für die Malerei

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

jede mögliche Hilfe? oder sollte ich mehr Details geben? Hier ist das Glas:

Antwort

1

Malen Sie Ihre Rechtecke zu einem BufferedImage, und zeichnen Sie dann diese BufferedImage innerhalb Ihrer PaintComponent-Methode. Sie können auch einschränken, wie viel neu gezeichnet wird, indem Sie eine der repaint(...) Überschreibungen verwenden, die die genaue rechteckige Region angeben, die neu gezeichnet werden soll.

So könnte Ihre Methode paintcomponent, da dies so einfach sein:

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

Mit Zeichnung Änderungen an der img BufferedImage gemacht.

Unter der Annahme, dass Sie einen Swing-Timer verwenden die Zustandsänderungen zu Ihrem Modell zu fahren, könnten Sie

  1. ändert das Modell, und dann
  2. Update das BufferedImage auf den Modelländerungen basieren, und
  3. rufen Sie repaint(...) auf nur die aktualisierte Region.

Unvollständiger Code Versuch .... noch nicht getan!

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

und wo sollte ich die Zeichnung der ganzen Matrix setzen? (Irgendwann, wenn wir die Größe des jFrames ändern, muss das jPanel jedes Rechteck neu gezeichnet werden? Ich möchte hier irgendein Problem haben) und ich kann kein Rechteck statt Bild zeichnen? –

+0

@NazimeLakehal: siehe Update zur Antwort –

+0

ok danke, werde ich versuchen, meinen Code zu ändern, aber die einzige Möglichkeit, es zu zeichnen ist es, paintComponent zu überschreiben? –