2013-03-04 4 views
0

Я пытаюсь отобразить набор Mandelbrot на JPanel, и это мой код. Я действительно не понимаю, почему изображение, нарисованное на BufferedImage, не отображалось на моем JPanel. Может ли кто-нибудь показать мне проблему в моем коде, пожалуйста?метод paintComponent (Graphics g) не работает

public class MainPanel1 extends JPanel implements Runnable, MouseListener, MouseMotionListener{ 

BufferedImage image;// = new BufferedImage(); 
BufferedImage imageToSave; // off screen image for saving image 
int number_of_iteration; 
int width, height; // current width and height of the drawing panel 
int widthToSave, heightToSave; // off screen width and height for saving image 
double real_portion_max, real_portion_min, imagin_portion_max, imagin_portion_min; 
boolean dragging; 
double zoom = 1, viewX = 0.0, viewY = 0.0; 
private int mouseX, mouseY; // mouse position when the button was pressed 
private int dragX, dragY; // current mouse position during dragging 
Graphics graphics;  
Graphics graphicsToSave; // off screen graphics for saving image  
Thread thread; 

public MainPanel1(){  
    this.setPreferredSize(new Dimension(500, 400)); 
    this.setBorder(BorderFactory.createLineBorder(Color.BLACK));       
    this.imagin_portion_max = 1.6; 
    this.imagin_portion_min = -1.6; 
    this.real_portion_max = 2; 
    this.real_portion_min = -2; 
    this.number_of_iteration = 100; 
    this.setDoubleBuffered(true);         
    this.thread = null; 
    addMouseListener(this); 
    addMouseMotionListener(this); 
} 

@Override 
public void run() { 
    while (thread != null) { 
     while (draw()); 
     synchronized (this){ 
      try { 
        wait(); 
      }catch (InterruptedException exp){ 

      } 
     } 
    } 
}  

public void start(){ 
    redraw(); 
} 

private void redraw() { 
    if (thread != null && thread.isAlive()) { 
     thread.interrupt(); 
    } else { 
     thread = new Thread(this); 
     thread.setPriority(Thread.MIN_PRIORITY); 
     thread.start(); 
    } 
} 

public boolean draw(){ 
    Dimension size = this.getPreferredSize(); 
    if(image == null || width != size.width || height != size.height){ 
     width = size.width; 
     height = size.height; 
     image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
     graphics = image.getGraphics(); 
    } 

    for (int y = 0; y < height; y++){ 
     for (int x = 0; x < width; x++){ 
      double r = zoom/Math.min(width, height); 
      double dx = (real_portion_max - real_portion_min) * (x * r + viewX) + real_portion_min; 
      double dy = (imagin_portion_max - imagin_portion_min) * (y * r + viewY) + imagin_portion_min; 
      Color color = color(dx, dy); 
      graphics.setColor(color); 
      graphics.fillRect(x, y, 1, 1);     
     }    
    }     
    repaint(); 
    return false; 
} 

public Color color(double x, double y){ 
    double color_index; 
    color_index = computeMaldenbrot(new Complex(0.0, 0.0), new Complex(x, y)); 
    float h = (float) (color_index/number_of_iteration); 
    float b = 1.0f -h*h;   
return Color.getHSBColor((float) (0.1+h), 0.95f, b); 
} 

public double computeMaldenbrot(Complex number, Complex point){ 
    int iteration = 0; 
    while (iteration < number_of_iteration && number.modulusSquared() < 4){ 
     number = number.square().add(point); 
     iteration++; 
    } 
    return iteration; 
} 

@Override 
public void paintComponent(Graphics g){   
    //super.paint(g);     
    g.drawImage(image, 0, 0, this); 
    if (dragging) {//Draw dragging rectangular      
     g.setColor(Color.green); 
     g.setXORMode(Color.white); 
     int x = Math.min(mouseX, dragX); 
     int y = Math.min(mouseY, dragY); 
     double w = mouseX + dragX - 2 * x; 
     double h = mouseY + dragY - 2 * y; 
     double r = Math.max(w/width, h/height);//make sure this rectangular self-similar to screen 
     g.drawRect(x, y, (int) (width * r), (int) (height * r)); 
    } 

} 
+0

Вы вызвали метод 'start()'? – Zutty

ответ

2

В paintComponent() методе первой линии, что вы должны написать это:
super.paintComponent(g);
И, кстати, в то время как ваша первая итерация в run() метод после draw() метод возвращается, ваш поток висит постоянно из-за wait. И вас нигде не называют notify().
И как предложено @mKorbel, Вместо использования Thread используйте javax.swing.Timer при работе с компонентами Swing. И кроме этого javax.swing.SwingWorker также является вариантом для выполнения сложной задачи в течение длительного времени. Смотрите это official tutorial знать, как использовать javax.swing.SwingWorker API. И here для javax.swing.Timer API.

+1

использовать Swing Timer, скорее это беспокоит сговорность в Swing – mKorbel

+1

@mKorbel: да, абсолютно правильно ... –

+0

Спасибо за ваш совет! но у меня проблема: у меня есть кнопка рисования на моем основном фрейме, и этот mandelbrot нарисован на этой mainpanel всякий раз, когда нажата кнопка рисования. И эта функция работает отлично! Я имею в виду, когда я нажимаю кнопку рисования, изображение набора отображается на панели. Это означает, что приведенный выше код работает. Я просто не понимаю, почему он не отображает изображение при запуске программы :( –