2014-03-31 245 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

的链接感谢您的快速回答。尽管如此,我更感兴趣的是在特定的时刻画出动画。事实证明,绘图没有显示出来的原因是因为我没有适当地转换高度,这是我在发布后不久发现的。我现在可以看到我的图纸。对不起,浪费时间。 –