2017-09-11 2 views
0

J'ai besoin de faire un code java avec Threads (implémente Runnable()) pour un lycée. J'ai besoin de dessiner 4 fractales en même temps (avec thread.sleep()). J'ai déjà essayé presque tout ce que je savais, et ça ne marche toujours pas. J'ai donc nettoyé la source.Peindre des fractales simultanément

J'ai quatre classes (quatre fractales). Dans mon JPanel, j'appelle une méthode de peinture pour les dessiner (elles sont récursives). Quelqu'un peut-il me sauver s'il vous plaît?

public class MainPanel extends JPanel { 
FractalTree tree = new FractalTree(); 
FractalCircle circle = new FractalCircle(); 
FractalSquare square = new FractalSquare(); 
FractalCircle2 circle2 = new FractalCircle2(); 

@Override 
public void paint(Graphics g) { 
    setBackground(Color.black,g); 
    Graphics2D g2 = (Graphics2D) g; 
    g.setColor(Color.WHITE); 
    DrawBounds(g); 

    tree.drawTree(g,200,290,-90,9); 
    circle.drawCircle(g2,675,175,300); 
    square.drawSquares(g, 200, 525, 100,7); 
    circle2.drawCircle(g2,675,518,300); 
} 

public void DrawBounds(Graphics g){ 
    g.drawLine(0,350,900,350); 
    g.drawLine(450,0,450,700); 
} 

public void setBackground(Color c,Graphics g){ 
    g.fillRect(0, 0, 900, 700); 
} 

}

public class FractalSquare{ 
public void drawSquares(Graphics g,int x, int y, int side ,int size){ 
    g.setColor(Color.BLUE); 
    if(size >2){ 
     size--; 
     g.fillRect(x-side/2, y-side/2, side, side); 
     side = side/2; 
     x = x-side; 
     y = y-side; 
     drawSquares(g,x,y,side,size); 
     drawSquares(g,x+side*2,y,side,size); 
     drawSquares(g,x,y+side*2,side,size); 
     drawSquares(g,x+side*2,y+side*2,side,size); 
    } else return; 
} 

}

public class FractalCircle { 
public void drawCircle(Graphics2D g, float x, float y, float radius) { 
    g.setColor(Color.RED); 
    g.draw(new Ellipse2D.Float(x-radius/2, y-radius/2, radius,radius)); 
    if(radius > 2) { 
     radius *= 0.75f; 
     drawCircle(g,x, y, radius); 
    } else return ; 
} 

}

public class FractalCircle2 { 

public void drawCircle(Graphics2D g, float x, float y, float radius) { 
    Color color = new Color(255,0,255); 
    g.setColor(color); 
    g.draw(new Ellipse2D.Float(x-radius/2, y-radius/2, radius,radius)); 
    if(radius > 1) { 
     radius *= 0.75f; 
     drawCircle(g,x + radius/2, y, radius/2); 
     drawCircle(g,x - radius/2, y, radius/2); 
    } else return ; 
} 

}

public class FractalTree { 

public void drawTree(Graphics g, int x1, int y1, double angle, int depth) { 
    g.setColor(Color.GREEN); 
    if (depth == 0) return; 
    int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 5.0); 
    int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 5.0); 
    g.drawLine(x1, y1, x2, y2); 
    drawTree(g, x2, y2, angle - 20, depth - 1); 
    drawTree(g, x2, y2, angle + 20, depth - 1); 

} 

+0

L'appel de 'setBackground (Color.black, g);' dans votre méthode 'paint' est une mauvaise idée. La peinture ne devrait peindre que l'état actuel, ne jamais le changer. En fait, vous devriez utiliser 'paintComponent' au lieu de' paint' et appeler d'abord 'super.paintComponent' – MadProgrammer

+0

Un autre choix serait de peindre un' BufferedImage' et de le peindre dans votre méthode 'paintComponent' – MadProgrammer

+0

t voir toute tentative d'utilisation de 'Thread'. Aussi, ces classes fractales sont-elles données? Ils semblent inutiles la façon dont ils sont mis en œuvre en tenant juste une méthode d'instruction. – user1803551

Répondre

0

Vous devrez rendre vos fractales en images séparées et les copier à l'écran au fur et à mesure que le rendu progressera. Swing fera le gros du travail pour vous si vous enroulez chaque fractale dans un JComponent.

Voici un exemple en utilisant un de vos Fractales:

public class FractalPanel extends JPanel { 
    final FractalSquare square = new FractalSquare(450, 350); 

    public FractalPanel() { 
     add(square); 
    } 

    public static void main(String[] args) { 
     FractalPanel fractalPanel = new FractalPanel(); 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(fractalPanel); 
     frame.pack(); 
     frame.setVisible(true); 

     Thread squareThread = new Thread(() -> { 
      try { 
       fractalPanel.square.render(); 
      } catch (InterruptedException e) { 
       System.err.println("Interrupted"); 
      } 
     }); 
     squareThread.start(); 
    } 
} 

class Fractal extends JComponent { 
    final BufferedImage image; 
    final Graphics2D offscreenGraphics; 

    public Fractal(int width, int height) { 
     setPreferredSize(new Dimension(width, height)); 
     image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
     offscreenGraphics = image.createGraphics(); 
    } 

    // Copy the offscreen image to the main graphics context 
    @Override 
    public void paint(Graphics g) { 
     Graphics2D g2 = (Graphics2D) g; 
     synchronized (image) { // synchronize with the render thread 
      g2.drawImage(image, 0, 0, null); 
     } 
    } 
} 

class FractalSquare extends Fractal { 
    public FractalSquare(int width, int height) { 
     super(width, height); 
    } 

    public void render() throws InterruptedException { 
     drawSquares(getWidth()/2, getHeight()/2, 100, 7); 
    } 

    public void drawSquares(int x, int y, int side, int size) throws InterruptedException { 

     // Sleep for 10ms between frames 
     Thread.sleep(10); 

     if (size > 2) { 
      size--; 

      synchronized (image) { // synchronize with the draw thread 
       offscreenGraphics.setColor(Color.BLUE); 
       System.out.printf("Filling [%d, %d, %d, %d]\n", x - side/2, y - side/2, side, side); 
       offscreenGraphics.fillRect(x - side/2, y - side/2, side, side); 
      } 

      // Tell Swing that we've updated the image and it needs to be redrawn 
      repaint(); 

      side = side/2; 
      x = x - side; 
      y = y - side; 
      drawSquares(x, y, side, size); 
      drawSquares(x + side * 2, y, side, size); 
      drawSquares(x, y + side * 2, side, size); 
      drawSquares(x + side * 2, y + side * 2, side, size); 
     } 
    } 
} 
0

Dans le JFrame qui contient votre MainPanel, ajoutez ce code (un Thread privé et son instance quelque part dans le constructeur):

private Thread threadRepaint; 

... 

threadRepaint = new Thread(new Runnable() { 
    @Override 
    public void run() { 
     while (true) { 
      try { 
       yourPanel.repaint(); 

       FractalSquare.decreaseLimit(); 
       FractalCircle.decreaseLimit(); 
       FractalCircle2.decreaseLimit(); 
       FractalTree.decreaseLimit(); 

       Thread.sleep(1000); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
}); 

threadRepaint.start(); 

L'idée sous-jacente est que le Thread doit diminuer la limite de vos fractales chaque seconde (1000ms).

Dans chacune de vos classes fractales, vous devez changer les conditions à quelque chose comme ceci, et aussi ajouter une variable statique. De cette façon, vous verrez une progression à chaque itération.

Pour FractalSquare, il arrête quand il arrive à 2:

private static limit = 10; 

... 

public static void decreaseLimit() { 
    if (limit > 2) limit--; 
} 

... 
    // Inside your drawSquares method 

    if (size > limit){ 
     ... 
    } else return; 

Il est fondamentalement la même idée pour chacun de vos autres Fractales: vous définissez une limite supérieure qui diminuera au fil du temps (chaque itération de le fil). La limite décroissante donnera l'illusion de la progression à chaque itération.

+0

Qu'est-ce que cette limite a à voir avec la question? La question demande comment dessiner 4 fractales simultanément et votre question ne répond pas à cela. – user1803551