2016-07-29 71 views
1

所以我必須創建一個帶Swing的Sierpinski墊片的實現。 我不能使用遞歸或三角形。我必須使用以下 算法:Java Swing中的Sierpinski墊片實現有時只出現

選擇3個點來定義一個三角形。

選擇其中一個頂點作爲當前循環50,000次: 隨機選擇一個頂點作爲目標。 在目標和當前之間的中點畫一個像素。 使目前的中點。

在下面的圖片是我有時會編譯,但有些時候它會彈出並消失,或根本不會顯示。如果它顯示出來,然後我調整它消失的窗口大小(我不關心這個,但是如果它有幫助的話)。我編譯時只能生成下面的圖像(大約1/3時間)。圖片下方是我的代碼,分爲兩類。

Image of when it works

import java.awt.*; 
import javax.swing.JFrame; 


public class SierpinskiGasket { 

    public static void main(String[] args) { 
     JFrame frame = new JFrame(); 
     frame.setTitle("SierpinskiGasket"); 
     frame.setSize(630,580); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 


     drawSierpinski Sierpinski = new drawSierpinski(); 

     frame.add(Sierpinski); 

     frame.setVisible(true); 

     } 
    } 




import javax.swing.*; 
import java.awt.*; 


public class drawSierpinski extends JPanel{ 

    Point point1 = new Point(10,550), 
      point2 = new Point(300,30), 
      point3 = new Point(600,555), 
      current = point1, target; 
    private int count = 0; 


    public void paintComponent(Graphics g){ 
     super.paintComponent(g); 

      while(count<= 50000){ 
       int choice = (int)(Math.random()*3); 
       switch(choice){ 
        case 0: target = point1; break; 
        case 1: target = point2; break; 
        case 2: target = point3; break; 
        default: System.exit(0); 

       } 
       current = midpoint(current,target); 
       g.drawLine(current.x,current.y,current.x,current.y); 

       count++; 
      } 
    } 

    public Point midpoint(Point a, Point b){ 
     return new Point((Math.round(a.x+b.x)/2), 
         (Math.round(a.y+b.y)/2)); 
    } 


} 

我假設它有事情做與Swing如何做多線程,但不幸的是我沒有對如何解決它太多的知識。非常感謝您的幫助!

回答

2

這個循環:

while(count<= 50000) { 

    // .... 

} 

可能需要一段時間才能完成,同時將在它的最關鍵點完全阻塞Swing事件線程 - 同時借鑑。更重要的是,任何簡單的重新繪製都會觸發循環重新運行,並再次凍結您的GUI。

解決方案:在paintComponent外部進行繪圖。相反,創建BufferedImage作爲JPanel的大小,獲取圖像的Graphics對象,在BufferedImage中繪製三角形的隨機點,然後在JPanel的paintComponent方法中顯示該圖像。您可以在程序啓動時繪製圖像,然後在完成後啓動GUI,也可以啓動GUI並在後臺線程中繪製到BufferedImage,並在完成時顯示它,如果這是好的你的GUI應該做的唯一一件事)。

例如:

import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.image.BufferedImage; 

import javax.swing.*; 

public class SierpTest { 
    public static final int BI_WIDTH = 630; 
    public static final int BI_HEIGHT = 580; 

    public static void main(String[] args) { 

     // do this stuff off the swing event thread 
     final BufferedImage sierpImg = new BufferedImage(BI_WIDTH, BI_HEIGHT, BufferedImage.TYPE_INT_ARGB); 
     Graphics g = sierpImg.getGraphics(); 

     // draw triangle with g here 

     g.dispose(); // always dispose of any Graphics you create yourself 

     // do this on the Swing event thread 
     SwingUtilities.invokeLater(() -> { 
      SierpPanel sierpPanel = new SierpPanel(sierpImg); // pass in image 
      JFrame frame = new JFrame("Siep Frame"); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.add(sierpPanel); 
      frame.pack(); // size it to the size of the JPanel 
      frame.setLocationRelativeTo(null); // center it 
      frame.setVisible(true); 
     }); 
    } 
} 

class SierpPanel extends JPanel { 
    private BufferedImage img = null; 

    public SierpPanel(BufferedImage img) { 
     this.img = img; 
    } 

    // so that JPanel sizes itself with the image 
    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet() || img == null) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(img.getWidth(), img.getHeight()); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if (img != null) { 
      g.drawImage(img, 0, 0, this); 
     } 
    } 
} 

例如:

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Point; 
import java.awt.image.BufferedImage; 

import javax.swing.*; 

public class SierpTest { 
    public static final int BI_WIDTH = 630; 
    public static final int BI_HEIGHT = 580; 
    private static final int MAX_COUNT = 100000; 

    public static void main(String[] args) { 

     // do this stuff off the swing event thread 
     Point point1 = new Point(10, 550); 
     Point point2 = new Point(300, 30); 
     Point point3 = new Point(600, 555); 
     Point current = point1; 
     Point target = current; 
     int count = 0; 

     final BufferedImage sierpImg = new BufferedImage(BI_WIDTH, BI_HEIGHT, BufferedImage.TYPE_INT_ARGB); 
     Graphics g = sierpImg.getGraphics(); 
     g.setColor(Color.WHITE); 
     g.fillRect(0, 0, BI_WIDTH, BI_HEIGHT); 
     g.setColor(Color.BLACK); 

     while (count <= MAX_COUNT) { 
      int choice = (int) (Math.random() * 3); 
      switch (choice) { 
      case 0: 
       target = point1; 
       break; 
      case 1: 
       target = point2; 
       break; 
      case 2: 
       target = point3; 
       break; 
      default: 
       System.exit(0); 

      } 
      current = midpoint(current, target); 
      g.drawLine(current.x, current.y, current.x, current.y); 

      count++; 
     } 

     // draw triangle with g here 

     g.dispose(); // always dispose of any Graphics you create yourself 

     // do this on the Swing event thread 
     SwingUtilities.invokeLater(() -> { 
      SierpPanel sierpPanel = new SierpPanel(sierpImg); // pass in image 
      JFrame frame = new JFrame("Siep Frame"); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.add(sierpPanel); 
      frame.pack(); // size it to the size of the JPanel 
      frame.setLocationRelativeTo(null); // center it 
      frame.setVisible(true); 
     }); 
    } 

    public static Point midpoint(Point a, Point b) { 
     return new Point((Math.round(a.x + b.x)/2), (Math.round(a.y + b.y)/2)); 
    } 
} 

class SierpPanel extends JPanel { 
    private BufferedImage img = null; 

    public SierpPanel(BufferedImage img) { 
     this.img = img; 
    } 

    // so that JPanel sizes itself with the image 
    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet() || img == null) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(img.getWidth(), img.getHeight()); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if (img != null) { 
      g.drawImage(img, 0, 0, this); 
     } 
    } 
} 

需要注意的是,如果你想獲得幻想,併爲它創建繪製三角形,並用延遲,則可以考慮使用任何一個Swing Timer或一個SwingWorker。