2012-04-17 8 views
1

내 GUI에 잘 알려진 Mandelbrot Fractal을 만들고 스윙 작업자를 사용하기로 결정한 이미지를 빠르게 만들려고합니다. doInBackground() 메서드에서 모든 픽셀의 색상을 계산 중이며 배열에 모든 색상을 적용하고 있습니다. done() 메서드에서 배열에 액세스하고 각 픽셀을 적절한 색으로 채 웁니다. EDT에서 색칠하는 동안 무거운 계산이 다른 스레드에서 수행됩니다. 필자는 BufferedImage에 저장되어 있다는 것을 알고 있지만 준비된 그림은 표시되지 않습니다. (파일을 하드 드라이브에 저장하거나 BufferedImage에 직접 액세스 할 수 있습니다. 또는 확대/축소하는 동안 - 전체 복사본을 만듭니다. BufferedImage -이 경우에는 적절한 이미지를 볼 수 있음). 나는 Java에 익숙하지 않지만 가능한 한 좋은 응용 프로그램을 원합니다. 내 코드는 다음과 여기에 있습니다 :SwingWorkers가 BufferedImage를 생성 한 후에 표시하지 않습니다.

public abstract class UniversalJPanel extends JPanel{ 

    protected BufferedImage image; 
    protected Graphics2D g2d; 

    protected int iterations = 100; // max number of iterations 
    protected double realMin = -2.0; // default min real 
    protected double realMax = 2.0;// default max real 
    protected double imaginaryMin = -1.6; // default min imaginary 
    protected double imaginaryMax = 1.6;// default max imaginary 
    protected int panelHeight; 
    protected int panelWidth; 
    protected Point pressed, released; // points pressed and released - used to calculate drawn rectangle 
    protected boolean dragged; // if is dragged - draw rectangle 
    protected int recWidth, recHeight,xStart, yStart; // variables to calculate rectangle 
    protected FractalWorker[] arrayOfWorkers; // array of Swing workers 



    public abstract int calculateIterations(Complex c); 
    public abstract double getDistance(Complex a, Complex b); 

    public void paintComponent(Graphics g){ 
     super.paintComponent(g); 
     panelHeight = getHeight(); 
     panelWidth = getWidth(); 
     image =new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); // creating new Bufered image 
     g2d= (Graphics2D) image.getGraphics(); 



     arrayOfWorkers= new FractalWorker[getHeight()]; // create new worker for each row and execute them 
     for(int q = 0; q < getHeight(); q++){ 
       arrayOfWorkers[q] = new FractalWorker(q); 
       arrayOfWorkers[q].execute(); 
     } 

     g.drawImage(image, 0, 0, null); // draw an image 

    } 

// *** getters, setters, different code// 

private class FractalWorker extends SwingWorker<Object, Object>{ 
    private int y; // row on which worker should work now 
    private Color[] arrayOfColors; // array of colors produced by workers 
    public FractalWorker(int z){ 
     y = z;  
    } 
    protected Object doInBackground() throws Exception { 

     arrayOfColors = new Color[getWidth()]; 

     for(int q=0; q<getWidth(); q++){ // calculate and insert into array proper color for given pixel 
      int iter = calculateIterations(setComplexNumber(new Point(q,y))); 
      if(iter == iterations){ 
       arrayOfColors[q] = Color.black; 
      }else{ 
       arrayOfColors[q] = Color.getHSBColor((float)((iter/ 20.0)), 1.0f, 1.0f); 
      } 
     }   
     return null; 
    } 
    protected void done(){ // take color from the array and draw pixel 
     for(int i = 0; i<arrayOfColors.length; i++){    
      g2d.setColor(arrayOfColors[i]); 
      g2d.drawLine(i, y, i, y); 
     } 
    } 

} 

답변

0

당신이 g.drawImage (...) 이미지의 현재 내용을 전화 http://pastebin.com/M2iw9rEY 구성 요소로 그려지고있다. 이 시점에서 SwingWorkers는 drawImage 호출 직전에 SwingWorkers를 시작하면서 작업을 완료하지 않았습니다. paintComponent 메소드로 SwingWorkers를 기동하지 말아주세요. 페인트 요구를 받으면 (자), 긴 드로잉 프로세스를 개시하기에는 너무 늦습니다.

더 좋은 해결책은 프로그램을 시작할 때 BufferedImage를 만든 다음 구성 요소의 크기가 변경 될 때 다시 만드는 것입니다. 다시 그리기가 필요할 때마다 SwingWorkers를 시작하고 그리기가 끝나면 구성 요소에서 repaint()를 호출해야합니다.

+0

SwingWorkers가 done() 메소드의 실행을 완료했는지 어떻게 확인할 수 있습니까? 내 프로그램을 시작할 때 BufferedImage를 작성하면 무슨 뜻인지 모르겠다. 나는 paintComponent() 메소드를 호출함으로써 그렇게 생각했다. "(...) 구성 요소의 크기가 변경되면 다시 만듭니다." - 구성 요소의 크기가 전혀 변경되지 않았습니다. 도와 줘서 고마워. – Trishia

+0

프로그램에서 paintComponent 메소드를 직접 호출하면 안됩니다. Swing이이를 수행합니다. 프로그램은 모든 paintComponent 호출에 신속하게 응답 할 수 있어야합니다. 따라서 paintComponent가 시작되기 전에 이미지를 준비하고 그려야합니다. 이미지의 내용이 변경되면 panel.repaint()를 호출하여 구성 요소를 다시 칠해야합니다. 그러면 paintComponent를 호출하는 Swing으로 연결됩니다. SwingWorkers가 끝났는지 확인하려면 done()의 끝에서 부울을 설정 한 다음 모든 작업자의 목록을 유지하고 불리언 검사를 반복합니다. –

관련 문제