2013-02-10 58 views
1

最近我一直在研究一個程序,用空的彩色正方形畫一個區域。它們在屏幕上的位置基於文本文件中的值1和2。 1s應該製造紅色盒子,2s應該製造綠色盒子。但是,當我運行該程序時,只有紅色框被繪製。我做了一些測試,發現重繪方法只被調用了兩次(有時出於某種原因),即使文件中有近300個值,並且應該爲每個值調用一次repaint()。這裏是我的代碼:重繪()不叫

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

爲什麼這段代碼不能正常工作?

+0

請永遠不要在ALLCAPS中命名課程。 「地圖」更容易閱讀 – supersam654 2013-02-10 23:01:52

+0

@ supersam654。對於那個很抱歉。我想我在一本我正在閱讀的書中找到了課程名稱。 – KrisC 2013-02-10 23:05:21

+0

你的輸入文件是什麼? – Raufio 2013-02-10 23:18:36

回答

3

只需添加到其他的答案,在這裏是一段代碼(基於你的),看起來已經好很多了(但仍然有一些問題,但你還沒有):

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像'ColoredShape'類! – MadProgrammer 2013-02-10 23:59:45

+0

這似乎工作。謝謝! – KrisC 2013-02-11 00:07:32

+0

@KrisC不要忘記正確關閉FileReader(最好的方法是將所有IO代碼封裝在try/finally塊中,並在finally中關閉FileReader)。這將避免鎖定文件。 – 2013-02-11 00:14:24

0

我看到的第一件事就是你一次只着色一種顏色。所以在這裏:

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

所有的形狀被繪製成相同的顏色,當你想以不同的顏色着色時。我認爲更好的做法是將所有形狀添加到列表中,跟蹤它們的顏色,然後調用repaint()一次。另外,我想paint方法改變的東西的影響:

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

而且,repaint纔會被調用兩次:它可能引發IOException。嘗試使用try {...} catch(IOException e) {...}塊,而不是將其投入生產線。例如:

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

它應該抱怨某些東西,如果它不正確。

+0

我不確定這是否會有所幫助,因爲repaint()方法仍然只被調用兩次。 – KrisC 2013-02-10 23:16:23

+0

它涉及「僅紅色印刷」問題 – Raufio 2013-02-10 23:40:14

3

繪畫是暫時的,或無狀態的。

repaint是向重繪管理器發出的一個「請求」,告訴它它應該在將來某個時候準備好時,它應該畫出屏幕的一部分,並認爲它是髒的。

這意味着,當你調用你g2.setColor(coulor)paint方法,它使用的最後一個值,它被設置爲(時paint叫)......這可能是RED

Raufio是對的,你應該提供顏色信息以及形狀。就我個人而言,我將設置第二個List,其中只包含Color個對象,其中Shape列表的每個索引都對應於Color中的Color

查看Painting in AWT and Swing瞭解更多關於如何在Swing中進行繪畫的細節。

現在,到愛發牢騷一部分;)

不建議重寫paint。有很多原因,paint負責調用一些重要的方法,包括執行非常重要的任務的paintChildrenpaintComponent

相反,你應該重寫paintComponent(並確保你打電話super.paintComponent

退房Performing Custom Painting瞭解更多詳情。

更新粗糙例如

原來這就是我說的是一個粗略的例子...

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解釋 – 2013-02-11 00:03:14