2016-12-18 29 views
0

因此,我編寫了一個程序來在我的Windows機器上顯示Julia集,但是paint()方法在調用完全相同時未被調用代碼到我的MacBook。Java - Paint()在Windows 10上調用,但不在OSX上10.10.5

全班:

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.event.MouseWheelEvent; 
import java.awt.event.MouseWheelListener; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

@SuppressWarnings("serial") 
public class JuliaSet extends JPanel implements MouseWheelListener { 

    public double width; 
    public double height; 
    public double pixToCoord; 
    public Complex c; 
    public double iterations = 100; 
    double xMin = -2; 
    double xMax = 2; 
    double centerY = 0; 

    public JuliaSet(double width, double height) { 
     this.width = width; 
     this.height = height + 31; 
     pixToCoord = (xMax - xMin)/width; 
     c = new Complex(0.285, 0.01); 
    } 

    public void setC(double x, double y) { 
     c.x = x; 
     c.y = y; 
    } 

    public void paint(Graphics g) { 

     pixToCoord = (xMax - xMin)/width; 
     double yMin = centerY - (height * pixToCoord/2.0); 
     Graphics2D g2 = (Graphics2D) g; 
     for (double y = 0; y <= height - 31; y++) { 
      for (double x = 1; x <= width; x++) { 
       Complex z = new Complex(x * pixToCoord + xMin, (-y + height) * pixToCoord + yMin); 
       double count = 0; 
       for (count = 0; count < iterations && z.magnitude() < 2; count++) { 
        z = z.multiply(z).add(c); 
       } 
       g2.setColor(Color.getHSBColor((float) (count/iterations), (float) 1.0, (float) (1.0 - (count/iterations)))); 
       g2.drawLine((int) x, (int) y - 31, (int) x, (int) y - 31); 
      } 
     } 
    } 

    @Override 
    public void mouseWheelMoved(MouseWheelEvent e) { 

     double x = (double) e.getX(); 
     double y = (double) e.getY() - 31; 
     x = x * pixToCoord + xMin; 
     double yMin = centerY - (height * pixToCoord/2.0); 
     double yMax = centerY + (height * pixToCoord/2.0); 
     y = (-y + height) * pixToCoord + yMin; 
     if (e.getWheelRotation() < 0) { 
      xMin += 0.25 * (x - xMin); 
      xMax -= 0.25 * (xMax - x); 
      yMin += 0.25 * (y - yMin); 
      yMax -= 0.25 * (yMax - y); 
     } else { 
      xMin -= (x - xMin)/3.0; 
      xMax += (xMax - x)/3.0; 
      yMin -= (y - yMin)/3.0; 
      yMax += (yMax - y)/3.0; 
     } 
     centerY = (yMax + yMin)/2.0; 
     this.repaint(); 
    } 

    public static void main(String[] args) throws InterruptedException { 

     JFrame frame = new JFrame(); 
     frame.setTitle("Julia Set"); 
     frame.setBounds(0, 0, 600, 631); 
     frame.setVisible(true); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JuliaSet p = new JuliaSet((double) frame.getWidth(), (double) frame.getHeight()); 
     frame.add(p); 
     //frame.addMouseWheelListener(p); 
     double angle = 0; 
     long time = System.currentTimeMillis(); 
     while (true) { 
      {Thread.sleep(16);} 
      angle += Math.PI/960.0; 
      if (angle >= Math.PI * 2.0) angle = 0; 
      p.setC(0.775 * Math.cos(angle), 0.775 * Math.sin(angle)); 
      p.repaint(); 
      System.out.println((int) (1000.0/(double) (System.currentTimeMillis() - time))); 
      time = System.currentTimeMillis(); 
     } 
    } 
} 

有什麼理由,這個代碼將在Windows,而不是OSX工作?

+1

請勿重寫paint()。自定義繪畫是通過重寫'paintComponent(...)'完成的。不要忘記調用super.paintComponent(...)。 Swing組件應該負責確定它們自己的大小,所以你應該重寫'getPreferredSize()'來返回組件的大小,然後你可以使用frame.pack()來獲得正確的框架大小。 – camickr

回答

3

您的代碼忽略了使用while (true)Thread.sleep的Swing線程規則以及可能的後臺線程中的Swing組件突變更改,因此您應該問的問題是它在任何系統上的工作原因。

建議:

  • 使用的SwingWorker創建您的後臺線程,並允許你做出對事件線程在Swing組件上有突變變化。
  • 在paintComponent中繪製,不繪製,並在您的覆蓋範圍內調用super的繪畫方法,如果您正確覆蓋此方法,則此處爲super.paintComponent(g)
  • 在後臺線程中執行復雜的數學運算或任何CPU或時間密集型處理,並避免在繪畫方法中執行此操作。這些方法只能用於繪畫和繪畫。

例如,這裏有一個使用的SwingWorker和圖形計算和繪製Mandelbrot集的部分(對不起,沒有Julia集的實現還)的一個樣本程序:

enter image description here

import java.awt.Color; 
    import java.awt.Dimension; 
    import java.awt.Graphics; 
    import java.awt.Graphics2D; 
    import java.awt.Point; 
    import java.awt.Rectangle; 
    import java.awt.Window; 
    import java.awt.Dialog.ModalityType; 
    import java.awt.event.ActionEvent; 
    import java.awt.event.ActionListener; 
    import java.awt.event.MouseAdapter; 
    import java.awt.event.MouseEvent; 
    import java.awt.image.BufferedImage; 
    import java.beans.PropertyChangeEvent; 
    import java.beans.PropertyChangeListener; 
    import java.util.concurrent.ExecutionException; 

    import javax.swing.*; 

    @SuppressWarnings("serial") 
    public class Mandel2 extends JPanel { 
     private static final int GUI_HEIGHT = 600; 
     private static final int GUI_WIDTH = 600; 
     private static final int MAX_ITERS = 50000; 
     private BufferedImage image = new BufferedImage(GUI_WIDTH, GUI_HEIGHT, 
       BufferedImage.TYPE_INT_ARGB); 
     private Rectangle zoomRect; 
     private double myX0 = -2.5; 
     private double myY0 = -2.0; 
     private double myX1 = 1.5; 
     private double myY1 = 2.0; 
     private JDialog waitDialog; 

     public Mandel2() { 
      final MyMouse myMouse = new MyMouse(); 

      int delayStartingCalc = 2 * 1000; // 2 second delay 
      Timer timer = new Timer(delayStartingCalc, new ActionListener() { 

       @Override 
       public void actionPerformed(ActionEvent e) { 
        addMouseListener(myMouse); 
        addMouseMotionListener(myMouse); 

        Rectangle myRect = new Rectangle(0, 0, GUI_WIDTH, GUI_HEIGHT); 
        createMandel(myRect); 
       } 
      }); 
      timer.setRepeats(false); 
      timer.start(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      if (isPreferredSizeSet()) { 
       return super.getPreferredSize(); 
      } 
      return new Dimension(GUI_WIDTH, GUI_HEIGHT); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      if (image != null) { 
       g.drawImage(image, 0, 0, this); 
      } 
      Graphics2D g2 = (Graphics2D) g; 
      if (zoomRect == null) { 
       return; 
      } 
      g2.setXORMode(Color.gray); 
      g2.draw(zoomRect); 
     } 

     private double screenToLogicalX(double screenX) { 
      return myX0 + (screenX * (myX1 - myX0))/GUI_WIDTH; 
     } 

     private double screenToLogicalY(double screenY) { 
      return myY0 + ((GUI_HEIGHT - screenY) * (myY1 - myY0))/GUI_HEIGHT; 
     } 

     private void createMandel(Rectangle myRect) { 
      double x0 = screenToLogicalX(myRect.x); 
      double y0 = screenToLogicalY(myRect.y + myRect.height); 
      double x1 = screenToLogicalX(myRect.x + myRect.width); 
      double y1 = screenToLogicalY(myRect.y); 

      myX0 = x0; 
      myY0 = y0; 
      myX1 = x1; 
      myY1 = y1; 

      MandelWorker mandelWorker = new MandelWorker(MAX_ITERS, x0, y0, x1, y1); 
      mandelWorker.addPropertyChangeListener(new MandelWorkerListener()); 
      mandelWorker.execute(); 
      if (waitDialog == null) { 
       Window win = SwingUtilities.getWindowAncestor(Mandel2.this); 
       JProgressBar jProgressBar = new JProgressBar(); 
       jProgressBar.setIndeterminate(true); 
       waitDialog = new JDialog(win, "Please Wait", ModalityType.APPLICATION_MODAL); 
       waitDialog.add(jProgressBar); 
       waitDialog.pack(); 
       waitDialog.setLocationRelativeTo(win); 
      } 
      waitDialog.setVisible(true); 
     } 

     private class MyMouse extends MouseAdapter { 
      private Point p; 

      @Override 
      public void mousePressed(MouseEvent e) { 
       p = e.getPoint(); 
      } 

      public void mouseDragged(MouseEvent e) { 
       zoomRect = createRect(e); 
       repaint(); 
      }; 

      @Override 
      public void mouseReleased(MouseEvent e) { 
       zoomRect = createRect(e); 
       repaint(); 
       createMandel(zoomRect); 
      } 

      private Rectangle createRect(MouseEvent e) { 
       int x = Math.min(p.x, e.getX()); 
       int y = Math.min(p.y, e.getY()); 
       int width = Math.abs(p.x - e.getX()); 
       int height = Math.abs(p.y - e.getY()); 
       return new Rectangle(x, y, width, height); 
      } 
     } 

     private class MandelWorkerListener implements PropertyChangeListener { 
      @Override 
      public void propertyChange(PropertyChangeEvent evt) { 
       if (evt.getNewValue() == SwingWorker.StateValue.DONE) { 
        waitDialog.setVisible(false); 
        waitDialog.dispose(); 
        MandelWorker worker = (MandelWorker) evt.getSource(); 
        try { 
         image = worker.get(); 
         zoomRect = null; 
         repaint(); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } catch (ExecutionException e) { 
         e.printStackTrace(); 
        } 
       } 
      } 
     } 

     private class MandelWorker extends SwingWorker<BufferedImage, Void> { 
      private int maxIters; 
      private double x1; 
      private double y1; 
      private double x2; 
      private double y2; 

      public MandelWorker(int maxIters, double x1, double y1, double x2, double y2) { 
       this.maxIters = maxIters; 
       this.x1 = x1; 
       this.y1 = y1; 
       this.x2 = x2; 
       this.y2 = y2; 
      } 

      @Override 
      protected BufferedImage doInBackground() throws Exception { 
       int[][] iterGrid = new int[GUI_HEIGHT][GUI_WIDTH]; 
       for (int i = 0; i < GUI_HEIGHT; i++) { 
        double y = y1 + i * (y2 - y1)/GUI_HEIGHT; 
        for (int j = 0; j < GUI_WIDTH; j++) { 
         double x = x1 + j * (x2 - x1)/GUI_WIDTH; 
         int iIndex = GUI_HEIGHT - i - 1; 
         iterGrid[iIndex][j] = calcMandel(x, y); 
        } 
       } 

       return render(iterGrid); 
      } 

      private BufferedImage render(int[][] iterGrid) { 
       int w = GUI_WIDTH; 
       int h = GUI_HEIGHT; 
       BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 
       Graphics2D g2 = img.createGraphics(); 
       for (int i = 0; i < w; i++) { 
        for (int j = 0; j < h; j++) { 
         if (iterGrid[i][j] < maxIters) { 
          String hexCode = String.format("#%06x", (0xFFFFFF & (32 * iterGrid[i][j]))); 
          g2.setColor(Color.decode(hexCode)); 
         } else { 
          g2.setColor(Color.CYAN); 
         } 
         g2.drawLine(j, i, j, i); 
        } 
       } 
       g2.dispose(); 
       return img; 
      } 

      private int calcMandel(double x, double y) { 
       Complex c = new Complex(x, y); 
       Complex z = new Complex(); 
       int iters = 0; 

       while (z.getMagnitude() < 2 && iters <= maxIters) { 
        z = z.multiply(z).add(c); 
        iters++; 
       } 
       return iters; 
      } 
     } 

     private class Complex { 
      private double real, imag; 

      // Constructors 
      public Complex() { 
       real = 0.0; 
       imag = 0.0; 
      } 

      public Complex(double real, double imag) { 
       this.real = real; 
       this.imag = imag; 
      } 

      // add given complex number to this one, returning the Complex result 
      public Complex add(Complex other) { 
       return new Complex(this.real + other.real, this.imag + other.imag); 
      } 

      // multiply given complex number by this one, returning the Complex 
      // result 
      public Complex multiply(Complex other) { 
       return new Complex((this.real * other.real) - (this.imag * other.imag), 
         (this.imag * other.real) + (this.real * other.imag)); 
      } 

      // get the magnitude of this complex number 
      public double getMagnitude() { 
       return Math.sqrt((real * real) + (imag * imag)); 
      } 
     } 

     private static void createAndShowGui() { 
      Mandel2 mainPanel = new Mandel2(); 

      JFrame frame = new JFrame("Mandel2"); 
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
      frame.getContentPane().add(mainPanel); 
      frame.setResizable(false); 
      frame.pack(); 
      frame.setLocationByPlatform(true); 
      frame.setVisible(true); 
     } 

     public static void main(String[] args) { 
      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        createAndShowGui(); 
       } 
      }); 
     } 
    } 
相關問題