2013-02-10 2 views
1

Récemment, j'ai travaillé sur un programme qui peint une zone avec des carrés de couleur vides. Leurs emplacements sur l'écran sont basés sur les valeurs 1 et 2 dans un fichier texte. Les 1 sont censés faire des boîtes rouges et les 2 sont censés faire des boîtes vertes. Cependant, lorsque je lance le programme, seules les cases rouges sont peintes. J'ai fait quelques tests et j'ai découvert que la méthode repaint est appelée seulement deux fois (parfois pour une raison quelconque), même s'il y a près de 300 valeurs dans le fichier, et repaint() devrait être appelée une fois pour chaque valeur. Voici mon code:Repaint() ne s'appelle pas

public class MAP extends JFrame { 

    public static void main(String[] args) throws IOException { 
     MAP map = new MAP(); 
    } 

    Shape shape; 
    int x = -32; 
    int y = 0; 
    ArrayList<Shape> shapes = new ArrayList<Shape>(); 
    Graphics2D g2; 
    Color coulor = null; 

    private class PaintSurface extends JComponent { 

     public PaintSurface() { 
     } 

     public void paint(Graphics g) { 
      g2 = (Graphics2D) g; 
      g2.setColor(coulor); 
      for (Shape s : shapes) { 
       g2.draw(s); 
      } 

     } 
    } 

    public MAP() throws FileNotFoundException, IOException { 
     JFrame frame = new JFrame(); 
     JPanel panel = new JPanel(); 
     frame.add(panel); 
     frame.setTitle("Grid Maker"); 
     frame.setSize(400, 200); 
     frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     frame.add(new PaintSurface(), BorderLayout.CENTER); 
     frame.setVisible(true); 

     readNextLine(); 
    } 

    private void readNextLine() throws IOException { 
     File file = new File("map.txt"); 
     BufferedReader in = new BufferedReader(new FileReader(file)); 
     String line = in.readLine(); 

     while (line != null) { 
      for (int i = 0; i < line.length(); i++) { 
       char c = line.charAt(i); 
       if (c == '1') { 
        coulor = Color.RED; 
        x += 32; 
        int smallX = x/32; 
        int smallY = y/32; 
        shape = new Rectangle2D.Float(x, y, 32, 32); 
        shapes.add(shape); 
        repaint(); 
       } else if (c == '2') { 
        coulor = Color.GREEN; 
        x += 32; 
        int smallX = x/32; 
        int smallY = y/32; 
        shape = new Rectangle2D.Float(x, y, 32, 32); 
        shapes.add(shape); 
        repaint(); 

       } 
      } 

      line = in.readLine(); 
      x = -32; 
      y += 32; 
     } 
    } 
} 

Pourquoi ce code ne fonctionne-t-il pas correctement?

+0

Ne JAMAIS JAMAIS donner de nom à une classe dans ALLCAPS. "Carte" est beaucoup plus facile à lire – supersam654

+0

@ supersam654. Désolé pour ça. Je pense que j'ai trouvé le nom de la classe dans un livre que je lisais. – KrisC

+0

que contient votre fichier d'entrée? – Raufio

Répondre

3

Juste pour ajouter d'autres réponses, ici est un morceau de code (basé sur le vôtre) qui semble déjà beaucoup mieux (encore il y a encore quelques problèmes, mais vous n'êtes pas encore là):

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Shape; 
import java.awt.geom.Rectangle2D; 
import java.io.BufferedReader; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.StringReader; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.JComponent; 
import javax.swing.JFrame; 

public class MAP extends JFrame { 

    public static void main(String[] args) throws IOException { 
     MAP map = new MAP(); 
    } 

    public static class ColoredShape { 
     private Shape shape; 
     private Color color; 

     public ColoredShape(Shape shape, Color color) { 
      super(); 
      this.shape = shape; 
      this.color = color; 
     } 

     public Shape getShape() { 
      return shape; 
     } 

     public Color getColor() { 
      return color; 
     } 
    } 

    int x = -32; 
    int y = 0; 
    List<ColoredShape> shapes = new ArrayList<ColoredShape>(); 
    Graphics2D g2; 

    private class PaintSurface extends JComponent { 

     public PaintSurface() { 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      g2 = (Graphics2D) g; 
      for (ColoredShape s : shapes) { 
       g2.setColor(s.getColor()); 
       g2.draw(s.getShape()); 
      } 

     } 
    } 

    public MAP() throws FileNotFoundException, IOException { 
     JFrame frame = new JFrame(); 
     frame.setTitle("Grid Maker"); 
     frame.setSize(400, 400); 
     frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     frame.add(new PaintSurface(), BorderLayout.CENTER); 
     frame.setVisible(true); 

     readNextLine(); 
    } 

    private void readNextLine() throws IOException { 
     BufferedReader in = new BufferedReader(new StringReader("11121\n1221\n2212\n221121\n111221\n11221\n222\n2222\n")); 
     String line = in.readLine(); 

     while (line != null) { 
      for (int i = 0; i < line.length(); i++) { 
       char c = line.charAt(i); 
       Color color = null; 
       if (c == '1') { 
        color = Color.RED; 
       } else if (c == '2') { 
        color = Color.GREEN; 
       } 
       if (color != null) { 
        shapes.add(new ColoredShape(new Rectangle2D.Float(x, y, 32, 32), color)); 
        x += 32; 
        repaint(); 
       } 
      } 

      line = in.readLine(); 
      x = -32; 
      y += 32; 
     } 
    } 
} 
+0

+1 Comme la classe 'ColoredShape'! – MadProgrammer

+0

Cela semble fonctionner. Merci! – KrisC

+0

@KrisC N'oubliez pas de fermer correctement votre FileReader (la meilleure approche consiste à envelopper tout votre code IO dans un bloc try/finally et fermez le FileReader dans le dernier). Cela évitera d'avoir des fichiers verrouillés. –

0

La première chose que je vois est que vous ne faites que colorier des formes une couleur à la fois. Donc ici:

public void paint(Graphics g) { 
    g2 = (Graphics2D) g; 
    g2.setColor(coulor);  //set the drawing color 
    for (Shape s : shapes) { 
     g2.draw(s);   //draw in that color 
    } 
} 

Toutes vos formes sont dessinées de la même couleur, lorsque vous souhaitez les colorier différemment. Je pense qu'une meilleure façon de faire est d'ajouter toutes vos formes dans votre liste, en gardant une trace de leur couleur, et en appelant repaint() une fois. En outre, je voudrais changer la méthode de peinture à quelque chose à l'effet de:

public void paint(Graphics g) { 
    g2 = (Graphics2D) g; 
    for (Shape s : shapes) { 
     g2.setColor(coulor[indexOfShape]); //set the drawing color 
     g2.draw(s);   //draw in that color 
    } 
} 

En outre, pour repaint seulement être appelé deux fois: Il est probablement jeter un IOException. Essayez d'utiliser un bloc try {...} catch(IOException e) {...} au lieu de simplement le jeter en haut de la ligne. Quelque chose comme:

private void readNextLine() { 
    try { 
     File file = new File("map.txt"); 
     BufferedReader in = new BufferedReader(new FileReader(file)); 
     String line = in.readLine(); 
     ... 
     ... 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

Il devrait se plaindre de quelque chose s'il ne lit pas correctement.

+0

Je ne suis pas sûr si cela aidera, puisque la méthode repaint() est encore seulement appelée deux fois. – KrisC

+0

Il traite le problème "seulement l'impression en rouge" – Raufio

3

La peinture est transitoire ou sans état.

repaint est une « demande » faite au gestionnaire de repeindre pour lui dire qu'il doit, à un moment donné à l'avenir, quand il est prêt, il devrait peindre une partie de l'écran, qu'il estime être sale.

Cela signifie que lorsque vous appelez g2.setColor(coulor) en vous méthode paint, il utilise la dernière valeur qu'il a été réglé sur (quand paint est appelé) .... ce qui est probablement RED. Raufio a raison, vous devriez fournir des informations de couleur avec les formes. Personnellement, je voudrais mettre en place un deuxième List qui contenait juste Color objets, où chaque index de la liste Shape correspondait directement à la Color dans le ColorList.

Consultez Painting in AWT and Swing pour plus de détails sur le fonctionnement de la peinture dans Swing.

Maintenant, la partie geignard;)

Il est recommandé de ne pas remplacer paint. Il ya beaucoup de raisons pour cela, paint est responsable de l'appel d'un certain nombre de méthodes importantes, y compris paintChildren et paintComponent, qui effectuent des tâches très importantes.

Au lieu de cela, vous devez remplacer paintComponent (et assurez-vous que vous appelez super.paintComponent)

Découvrez Performing Custom Painting pour plus de détails.

mise à jour avec l'exemple rugueux

C'est donc un exemple grossier de ce que je parle ...

enter image description here

public class TestPainting { 

    public static void main(String[] args) { 
     new TestPainting(); 
    } 

    public TestPainting() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (Exception ex) { 
       } 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new PaintingPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class PaintingPane extends JPanel { 

     private static final int WIDTH = 200; 
     private static final int HEIGHT = 200; 

     private List<Shape> shapes; 
     private List<Color> colors; 

     public PaintingPane() { 
      shapes = new ArrayList<>(25); 
      colors = new ArrayList<>(25); 

      for (int index = 0; index < (int) Math.round(Math.random() * 100); index++) { 

       int x = (int) Math.round(Math.random() * (WIDTH * 0.75f)); 
       int y = (int) Math.round(Math.random() * (HEIGHT * 0.75f)); 
       int width = (int) Math.round(Math.random() * (WIDTH * 0.25f)); 
       int height = (int) Math.round(Math.random() * (HEIGHT * 0.25f)); 

       if (width < 5) { 
        width = 5; 
       } 
       if (height < 5) { 
        height = 5; 
       } 

       if (x + width > WIDTH) { 
        x -= width - WIDTH; 
       } 
       if (y + height > HEIGHT) { 
        y -= height - HEIGHT; 
       } 
       if (x < 0) { 
        x = 0; 
       } 
       if (y < 0) { 
        y = 0; 
       } 

       Color color = ((int)Math.round(Math.random() * 2)) == 1 ? Color.RED : Color.GREEN; 

       shapes.add(new Rectangle(x, y, width, height)); 
       colors.add(color); 
      } 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(WIDTH, HEIGHT); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      for (int index = 0; index < shapes.size(); index++) { 
       g2d.setColor(colors.get(index)); 
       g2d.draw(shapes.get(index)); 
      } 
      g2d.dispose(); 

     } 
    } 
} 
+0

+1 pour les explications –