Създадох прозорец, който има голям JPanel, заемащ по-голямата част от областта, която ще се използва за анимиране на набор от фойерверки. Имам частен вътрешен клас AnimationPanel, който разширява JPanel. Замених paintComponent(), за да използвам буферирано изображение като фон. При натискане на бутона за стартиране ще стартира симулация, която ще анимира набора от фойерверки. В момента тази симулация извежда позициите към конзолата и генерира колекция, наречена моментна снимка, съдържаща всички фойерверки в определен момент от време.
В момента успешно нарисувах фона и малък правоъгълник, за да представя изстрелващата тръба, но когато се опитам да нарисувам фойерверките от моментната снимка, нищо не се показва. На този етап не съм загрижен за анимацията (все още се уча как да правя това с помощта на класа 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) и този (панел с фоново изображение и рисуване с мишката), но не са имали успех. Все още остана с фон и правоъгълник.