2013-03-04 105 views
0

我试图显示在JPanel上设置的Mandelbrot,这是我的代码。我真的不明白为什么在BufferedImage上绘制的图像没有显示在我的JPanel上。任何人都可以在我的代码中看到我的问题吗?方法paintComponent(图形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 2013-03-04 16:58:33

回答

2

paintComponent()方法,你应该写第一行是:
super.paintComponent(g);
顺便说一句,而返回的run()方法之后draw()方法的第一次迭代,你的线程挂起的永久因为wait。而你无处叫做notify()
正如@mKorbel所建议的,在处理Swing组件时,不要使用Thread,而应使用javax.swing.Timer。除此之外,javax.swing.SwingWorker也是执行长时间运行的复杂任务的选项。观看这个official tutorial知道如何使用javax.swing.SwingWorker API。和herejavax.swing.Timer API。

+1

使用摆动计时器,而不是在Swing – mKorbel 2013-03-04 18:02:43

+1

@mKorbel麻烦:是的绝对正确... – 2013-03-04 18:04:07

+0

感谢您的意见!但我在这里有一个问题:我的主框架上有一个绘制按钮,每当按下绘制按钮时,此mandelbrot都会绘制在此主面板上。这个功能完美地工作!我的意思是当我按下绘图按钮时,组的图像显示在面板上。这意味着上面的代码正在运行。我只是不明白为什么当我启动程序时它不显示图像:( – 2013-03-05 01:00:22