2014-03-31 123 views
1

我創建了一個窗口,其中有一個大的JPanel佔據了將用於製作一組煙花的區域的大部分區域。我有一個擴展JPanel的私有內部類AnimationPanel。我重寫了paintComponent()以便將緩衝圖像用作背景。按下啓動按鈕後,模擬將運行,這將激活一組煙花。此時,此模擬將位置輸出到控制檯,並生成一個名爲snapshot的集合,其中包含特定時間點的所有煙花。目前,我已經成功繪製了背景和一個小矩形來表示發射管,但是當我嘗試從快照中繪製煙花時,什麼也沒有顯示出來。在這一點上,我不關心動畫(仍然學習如何使用Timer類來完成此操作),但是我需要知道繪製將會起作用,所以我只是試圖繪製快照。在獲取快照後,我正在模擬結束時重新繪製animationPanel。背景圖片上的動畫效果

私有內部類AnimationPanel

private class AnimationPanel extends JPanel { 

    private BufferedImage background; 

    public AnimationPanel() { 
     super(); 
     try { 
      background = ImageIO.read(new File("background.jpg")); 
     } catch(IOException error) { 
      error.printStackTrace(); 
     } 
    } 

    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.drawImage(background,0,0,getWidth(),getHeight(),this); //this shows up 
     g.setColor(Color.RED); 
     g.fillRect(getWidth()/2, getHeight()-30, 10, 30); //this shows up 
     paintFireWorks(g); //this doesn't show up 
    } 

    private void paintFireWorks(Graphics g) { 
     if(snapshot != null) { 
      for(Firework item: snapshot) { 
       double[] position = item.getPosition(); 
       if(item instanceof Star){ 
        int x = (int)Math.round(position[0])+animationPanel.getWidth()/2; 
        int y = animationPanel.getHeight()-(int)Math.round(position[1]); 
        int r = ((Star) item).getRenderSize(); 
        g.fillOval(x,y,r,r); 
       } else if(item instanceof Spark){ 
        int x1 = (int)Math.round(position[0])+animationPanel.getWidth()/2; 
        int x2 = (int)Math.round(position[0])-((Spark)item).getRenderSize(); 
        int y1 = animationPanel.getHeight()-(int)Math.round(position[1]); 
        int y2 = animationPanel.getHeight()-(int)Math.round(position[1])+((Spark)item).getRenderSize(); 
        g.drawLine(x1,y1,x2,y2); 
       } 
      } 
     } 
    } 

} 

整個FireWorksWindow類:

import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import java.util.ArrayList; 

import javax.imageio.ImageIO; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class FireWorksWindow extends JFrame { 

//DIMENSIONS AND POSITIONS 
private final int STARTING_POS_X = 1600; 
private final int STARTING_POS_Y = 100; 

//CONTAINERS AND COMPONENTS 
private AnimationPanel animationPanel; 
private JPanel controlPanel, sliderPanel; 
private Box controlBox; 
private JLabel windSliderLabel, angleSliderLabel; 
private JSlider windSpeed, launchAngle; 
private JButton startButton, pauseButton, exitButton; 

//TIMER 
private Timer animationTimer; 

//COLLECTIONS 
ArrayList<Particle> fireworks; 
ArrayList<Particle> snapshot; 

//CONSTRUCTOR 
public FireWorksWindow() { 
    setTitle("Roman Candle Animation"); 
    setLocation(STARTING_POS_X,STARTING_POS_Y); 
    setDefaultCloseOperation(EXIT_ON_CLOSE); 

    sliderPanel = new JPanel(); 
    GridBagLayout sliderGrid = new GridBagLayout(); 
    sliderPanel.setLayout(sliderGrid); 
    initSliders(); 
    initLabels(); 
    addComponent(sliderGrid, windSliderLabel,  1,1,new Insets(5,10,5,10)); 
    addComponent(sliderGrid, angleSliderLabel,  1,2,new Insets(5,10,5,10)); 
    addComponent(sliderGrid, windSpeed,    2,1,new Insets(5,10,5,10)); 
    addComponent(sliderGrid, launchAngle,   2,2,new Insets(5,10,5,10)); 

    controlPanel = new JPanel(); 
    controlPanel.setLayout(new BoxLayout(controlPanel,BoxLayout.X_AXIS)); 
    initButtons(); 
    initControlBox(); 
    controlPanel.add(controlBox); 
    controlPanel.setBorder(BorderFactory.createLineBorder(Color.MAGENTA , 3)); 

    animationPanel = new AnimationPanel(); 
    animationPanel.setSize(new Dimension(750,500)); 
    animationPanel.setMinimumSize(new Dimension(animationPanel.getWidth(),animationPanel.getHeight())); 
    animationPanel.setPreferredSize(new Dimension(animationPanel.getWidth(),animationPanel.getHeight())); 

    add(animationPanel,BorderLayout.CENTER); 
    add(controlPanel,BorderLayout.SOUTH); 
    pack(); 
    setMinimumSize(new Dimension(getWidth(),getHeight())); 
    sliderPanel.setMaximumSize(new Dimension(sliderPanel.getWidth(), sliderPanel.getHeight())); 
} 

//CONVENIENCE METHODS 
private void addComponent(GridBagLayout layout, Component component, int row, int column, Insets padding) { 
    GridBagConstraints constraints = new GridBagConstraints(); 
    constraints.gridx = column; 
    constraints.gridy = row; 
    constraints.insets = padding; 
    layout.setConstraints(component, constraints); 
    sliderPanel.add(component); 
} 

private void initLabels() { 
    windSliderLabel = new JLabel("Wind Speed"); 
    angleSliderLabel = new JLabel("Launch Angle"); 
} 

private void initSliders() { 
    windSpeed = new JSlider(-20,20); 
     windSpeed.setMajorTickSpacing(10); 
     windSpeed.setMinorTickSpacing(5); 
     windSpeed.setPaintTicks(true); 
     windSpeed.setPaintLabels(true); 
    launchAngle = new JSlider(-15,15); 
     launchAngle.setMajorTickSpacing(5); 
     launchAngle.setMinorTickSpacing(1); 
     launchAngle.setPaintTicks(true); 
     launchAngle.setPaintLabels(true); 
} 

private void initButtons() { 
    startButton = new JButton("Start"); 
    startButton.addActionListener(new StartHandler()); 
    pauseButton = new JButton("Pause"); 
    pauseButton.addActionListener(new PauseHandler()); 
    exitButton = new JButton("Exit"); 
    exitButton.addActionListener(new ExitHandler()); 
} 

private void initControlBox() { 
    controlBox = Box.createHorizontalBox(); 
    controlBox.add(Box.createHorizontalStrut(10)); 
    controlBox.add(sliderPanel); 
    controlBox.add(Box.createHorizontalStrut(30)); 
    controlBox.add(startButton); 
    controlBox.add(Box.createHorizontalStrut(10)); 
    controlBox.add(pauseButton); 
    controlBox.add(Box.createHorizontalGlue()); 
    controlBox.add(Box.createHorizontalStrut(10)); 
    controlBox.add(Box.createHorizontalGlue()); 
    controlBox.add(exitButton); 
    controlBox.add(Box.createHorizontalStrut(10)); 
} 

//ACTION LISTENERS 
public class WindAdjustListener implements ActionListener{ 
    public void actionPerformed(ActionEvent e) { 

    } 

} 

public class AngleAdjustListener implements ActionListener{ 
    public void actionPerformed(ActionEvent e) { 

    } 

} 

public class StartHandler implements ActionListener { 
    public void actionPerformed(ActionEvent event) { 
     System.out.println("START Pressed"); 
     startButton.setText("Reset"); 
     repaint(); 
     runAnimation(); 
     startButton.setText("Start"); 
    } 
} 

public class PauseHandler implements ActionListener { 
    public void actionPerformed(ActionEvent event) { 
     System.out.println("PAUSE Pressed"); 
    } 
} 

public class ExitHandler implements ActionListener { 
    public void actionPerformed(ActionEvent event) { 
     if(animationTimer != null) 
      if(animationTimer.isRunning()) 
       animationTimer.stop(); 
     System.exit(0); 
    } 
} 

public class AnimationClock implements ActionListener { 
    public void actionPerformed(ActionEvent arg0) { 

    } 
} 

//ACCESSORS 
public double[] getSliderValues() { 
    double[] sliders = new double[2]; 
    sliders[0] = windSpeed.getValue(); 
    sliders[1] = launchAngle.getValue(); 
    return sliders; 
} 

//OTHER METHODS 
public void runAnimation() { 
    double[] inputs = getSliderValues(); 
    double wind = inputs[0]; 
    double launchAngle = inputs[1]; 
    double timeInterval = 0.05;  // seconds 
    ParticleManager manager = null; 
    try { 
     manager = new ParticleManager(wind, launchAngle); 
    } catch (EnvironmentException except) { 
     System.out.println(except.getMessage()); 
     return; 
    } catch (EmitterException except) { 
     System.out.println(except.getMessage());    
     return; 
    } 
    System.out.println("Counts:"); 
    System.out.println("time\tStars\tSparks\tLaunchSparks"); 
    double time = 0; 
    manager.start(time); 
    fireworks = manager.getFireworks(time); 
    do { 
     //if (time % 0.5 == 0) 
      showTypesCount(fireworks, time); 
     if (Math.abs(time - 2.0) < timeInterval) 
      snapshot = fireworks; 
     time += timeInterval; 
     fireworks = manager.getFireworks(time); 
    } while (fireworks.size() > 0); 
    showFireworks(snapshot, 2.0); 
    animationPanel.repaint(); 
} 

public void showFireworks(ArrayList<Particle> fireworks, double time) { 
    if (fireworks == null) 
     return; 
    System.out.printf("\nAt time%5.2f seconds:\n", time); 
    System.out.println("Type\t\tPosition (metres)"); 
    for (Particle firework : fireworks) 
     System.out.println(firework); 
} 

public void showTypesCount(ArrayList<Particle> fireworks, double time) { 
    int starCount = 0; 
    int sparkCount = 0; 
    int launchSparkCount = 0; 
    for (Particle firework : fireworks) { 
     if (firework instanceof Star) 
      starCount++; 
     else if (firework instanceof LaunchSpark) 
      launchSparkCount++; 
     else 
      sparkCount++; 
    } 
    System.out.printf("%5.2f\t", time); 
    System.out.println(starCount + "\t" + sparkCount + "\t" + launchSparkCount); 
} 

private class AnimationPanel extends JPanel { 

    private BufferedImage background; 

    public AnimationPanel() { 
     super(); 
     try { 
      background = ImageIO.read(new File("background.jpg")); 
     } catch(IOException error) { 
      error.printStackTrace(); 
     } 
    } 

    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.drawImage(background,0,0,getWidth(),getHeight(),this); //this shows up 
     g.setColor(Color.RED); 
     g.fillRect(getWidth()/2, getHeight()-30, 10, 30); //this shows up 
     paintFireWorks(g); //this doesn't show up 
    } 

    private void paintFireWorks(Graphics g) { 
     if(snapshot != null) { 
      for(Firework item: snapshot) { 
       double[] position = item.getPosition(); 
       if(item instanceof Star){ 
        int x = (int)Math.round(position[0])+animationPanel.getWidth()/2; 
        int y = animationPanel.getHeight()-(int)Math.round(position[1]); 
        int r = ((Star) item).getRenderSize(); 
        g.fillOval(x,y,r,r); 
       } else if(item instanceof Spark){ 
        int x1 = (int)Math.round(position[0])+animationPanel.getWidth()/2; 
        int x2 = (int)Math.round(position[0])-((Spark)item).getRenderSize(); 
        int y1 = animationPanel.getHeight()-(int)Math.round(position[1]); 
        int y2 = animationPanel.getHeight()-(int)Math.round(position[1])+((Spark)item).getRenderSize(); 
        g.drawLine(x1,y1,x2,y2); 
       } 
      } 
     } 
    } 

} 

}

任何想法,爲什麼煙花圖紙都沒有顯示出來?我試圖適應這個答案(Dynamic Graphics Object Painting)和這個(panel with image background and mouse draw)中顯示的方法,但沒有成功。仍然堅持一個背景和一個矩形。

+0

1)爲了更快地獲得更好的幫助,請發佈[MCVE](http://stackoverflow.com/help/mcve)(最小完整和可驗證示例)。 2)獲取圖像的一種方法是通過熱鏈接到[本答案](http://stackoverflow.com/a/19209651/418556)中看到的圖像。 –

+0

@Andrew Thompson絕對會從現在開始 - 感謝主題 –

回答

2

在此基礎上...

public class StartHandler implements ActionListener { 
    public void actionPerformed(ActionEvent event) { 
     System.out.println("START Pressed"); 
     startButton.setText("Reset"); 
     repaint(); 
     runAnimation(); 
     startButton.setText("Start"); 
    } 
} 

您從事件指派線程

的背景下,你runAnimation方法,那麼你這樣做內調用runAnimation ...

do { 
    //... 
} while (fireworks.size() > 0); 

這是阻止EDT並阻止處理新事件,包括重新繪製請求

看看Concurrency in Swing

簡單的解決辦法是使用Swing Timer這將允許您卸載一個小等待進入的背景,但它是在美國東部時間範圍內觸發...

+0

的鏈接感謝您的快速回答。儘管如此,我更感興趣的是在特定的時刻畫出動畫。事實證明,繪圖沒有顯示出來的原因是因爲我沒有適當地轉換高度,這是我在發佈後不久發現的。我現在可以看到我的圖紙。對不起,浪費時間。 –