在烟花程序中启动一个线程

时间:2016-02-06 15:20:54

标签: java multithreading swing graphics

我正在编写一个小烟花软件,用户可以选择颜色,爆炸时间,保险丝的持续时间,大小和形状,添加其他保险丝然后启动它们,这会创建一个新的框架,保险丝出现在他们给定的时间和给定的持续时间。

我将问题分为不同的类别,Etincelles用于火花,Fusee用于每个保险丝,然后动画创建框架,用户可以设置保险丝。他们每个人都有一个绘画功能:peindreEtincelle(图形g),然后是使用peindreEtincelle的peindreFusee(图形g),然后是使用peindreFusee的动画中的绘画。每个保险丝应该有自己的线程,以便我可以控制何时停用它,我已经在测试类中测试了peindreFusee和peindreEtincelle并且它们工作正常。由于Fusee类中有一个线程,我编写了一个使用peindreFusee的函数run(),如下所示:

每个线程的每个线程的run()类Fusee:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.math.*;


public class Fusee implements Runnable {
  //ATTRIBUTES
  public int num, puissEtincelles, nbEtincelles;
  public double xf, yf, duree, tpsDepart ;
  public boolean active = true ;
  public String forme ;
  public Thread anim ;
  public Color couleur ;
  public static double DIV = 1%(Math.sqrt(2)) ;
  public LinkedList<Etincelle> liste;
  public Graphics g;

  //CONSTRUCTOR
  public Fusee(int numero){
    num = numero ;
    couleur = Color.red ;
    nbEtincelles = 1 + 8^puissEtincelles; 
    anim = new Thread(this) ; 
    liste = new LinkedList<Etincelle>() ; /
    liste.add(new Etincelle(xf,yf));  
    for (int k =1 ; k<=puissEtincelles ;k++){
        liste.add(new Etincelle(xf+10*k,yf));
        liste.add(new Etincelle(xf-10*k,yf));
        liste.add(new Etincelle(xf,yf+10*k));
        liste.add(new Etincelle(xf,yf-5*k));
        liste.add(new Etincelle(xf+10*k*DIV,yf+10*k*DIV));
        liste.add(new Etincelle(xf+10*k*DIV,yf-10*k*DIV));
        liste.add(new Etincelle(xf-10*k*DIV,yf+10*k*DIV));
        liste.add(new Etincelle(xf-10*k*DIV,yf-10*k*DIV));
    }
}

//METHODS
public void run(){
    while(active == true){
        if (tpsDepart == 0) {
          if (duree>0){ 
             duree = duree-0.01 ;
             peindreFusee(g);
          }
          else if (duree == 0){
             active = false ; 
          }
        }
        else if (tpsDepart >0){
            tpsDepart = tpsDepart - 0.01 ; 
        }
    }
    try {
        Thread.sleep(10);//pause d'un centième seconde
      }
      catch(InterruptedException e) {
        System.out.println(e);
      }
}

现在我想通过手动设置然后启动线程来测试一个保险丝的动画;但只有一个涂成黑色的新框架出现,没有保险丝。我的测试类看起来像这样:

测试动画的类:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.math.*;

public class TestFusee extends Frame {
//ATTRIBUTS
public Fusee fus ;
public int w,h ;

//CONSTRUCTOR
public TestFuseeAnimee() {
    this.setLocation(100, 100);
    this.setSize(1200,700);
    w = this.getSize().width ;
    h = this.getSize().height ;
    fus = new Fusee(1);
    fus.active = true ;
    fus.xf = w/2 ;
    fus.yf = h/2 ;
    fus.couleur = Color.red ;
    fus.forme = "etoile" ;
    fus.puissEtincelles = 2 ;
    fus.tpsDepart = 10 ;
    fus.duree = 20 ;
    addWindowListener(new EcouteurPourFermetureFenetre());
}

//METHOD
public void paint(Graphics g){
    w = this.getSize().width ;
    h = this.getSize().height ;
    g.setColor(Color.black);
    g.fillRect(0, 0, w, h);
    fus.g = g; 
    fus.anim.start(); 
}


//MAIN
public static void main(String [] abs){
    TestFuseeAnimee fen = new TestFuseeAnimee();
    fen.setVisible(true) ;
} 

以下是peindreFusee()实际绘画的一个示例(此处为橙色圆点,表单和颜色由用户选择)

Example of a fuse after painting

有谁能告诉我我的代码有什么问题?这将非常有帮助。

非常感谢:)

以下是测试程序的缺失类:

班级Etincelle:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;


public class Etincelle {
//ATTRIBUTS
public Color couleur ;
public double duree, x, y ;
public String forme ;

//CONSTRUCTOR
public Etincelle(double a, double b) {
    x=a;
    y=b;
    forme = "croix";
    couleur=Color.red ;
}

//METHODES
public void peindreEtincelle(Graphics g) {
    g.setColor(couleur);
    if (forme == "croix") {
        g.drawLine((int)x-5, (int)y, (int)x+5, (int)y);
        g.drawLine((int)x, (int)y-5, (int)x, (int)y+5); 
    }
    else if (forme == "point"){
        g.fillOval((int)x, (int)y, 8, 8);
    }
    else if (forme=="etoile"){
        g.drawLine((int)x-5, (int)y, (int)x+5, (int)y);
        g.drawLine((int)x, (int)y-5, (int)x, (int)y+5); 
        g.drawLine((int)x-5, (int)y-5, (int)x+5, (int)y+5);//pose les points de l'étoile, qui ici ressemble plus à un carré car plus facile à coder et peu visible (petit)
        g.drawLine((int)x-5, (int)y+5, (int)x+5, (int)y-5); 
    }
}

}

EcouteurPourFermetureFenetre课程:

import java.awt.event.*;

public void windowClosing(WindowEvent w) {
w.getWindow().dispose() ;  
System.exit(0);  

}

}

1 个答案:

答案 0 :(得分:0)

所以...我觉得这很接近你想要的(没有延迟......无法解决这个问题),对不起切换任何法语和英语:)

fireworks

第1步 - 定义可绘制界面

public interface Drawable {
    void drawOn(Graphics g);
}

第2步 - 定义一个实现此Drawable的抽象Etincelle

public abstract class Etincelle implements Drawable {

    public double x, y;
    public Color couleur;

    public Etincelle(double x, double y, Color couleur) {
        this.x = x;
        this.y = y;
        this.couleur = couleur;
    }

    public Etincelle(double x, double y) {
        this(x, y, Color.red);
    }

    protected abstract void peindreEtincelle(Graphics g);

    @Override
    public void drawOn(Graphics g) {
        Color previous = g.getColor();

        g.setColor(couleur);
        peindreEtincelle(g);

        g.setColor(previous);
    }
}

第3步 - 定义Etincelle的扩展,在这里我们做Point forme。

public class PointEtincelle extends Etincelle {

    public static final String FORME = "POINT";
    private int radius = 8;

    public PointEtincelle(double a, double b) {
        super(a, b);
    }

    public PointEtincelle(double x, double y, Color couleur) {
        super(x, y, couleur);
    }

    @Override
    protected void peindreEtincelle(Graphics g) {
        g.fillOval((int) x - radius / 2, (int) y - radius / 2, radius, radius);
    }
}

和Croix forme

public class CroixEtincelle extends Etincelle {

    public static final String FORME = "CROIX";

    public CroixEtincelle(double a, double b) {
        super(a, b);
    }

    public CroixEtincelle(double x, double y, Color couleur) {
        super(x, y, couleur);
    }

    @Override
    protected void peindreEtincelle(Graphics g) {
        g.drawLine((int) x - 5, (int) y, (int) x + 5, (int) y);
        g.drawLine((int) x, (int) y - 5, (int) x, (int) y + 5);
    }

}

我也有一个Etoille forme,但我认为你明白了。

第4步 - 定义一个Fusee,在这里用于所有目的,只是一个非常大的Etincelle,所以我们将这样定义。这可能是最复杂的课程,但我做了一些反思魔法,以从#34; CROIX&#34;的字符串值中获取不同的表格。和#34; POINT&#34;,例如。这将让你以后很容易地添加不同的版本。注释掉的部分&#34;工作&#34; ...你可以玩它们取消注释它们,但它们可以清除&#34;清除&#34;离开旧的Etincelle基本上是通过重绘黑色的形状。我不确定Fusee是否应该“离开”#34;或不,所以我留下他们评论。

public class Fusee extends Etincelle {

    private static final HashMap<String, Class<? extends Etincelle>> ETINCELLE_MAP = new HashMap<String, Class<? extends Etincelle>>() {{
        put(CroixEtincelle.FORME, CroixEtincelle.class);
        put(PointEtincelle.FORME, PointEtincelle.class);
        put(EtoileEtincelle.FORME, EtoileEtincelle.class);
    }};

    //ATTRIBUTES
    public int size;
    public long duree;
    public String forme;

    //CONSTRUCTOR
    public Fusee(double x, double y, String forme, Color couleur, int size, long duree) {
        super(x, y, couleur);
        this.size = size;
        this.forme = forme;
        this.duree = duree;
    }

    private static LinkedList<Drawable> getPattern(double xf, double yf, Color couleur, String forme, int puissEtincelles) {
        LinkedList<Drawable> liste = new LinkedList<Drawable>();

        if (ETINCELLE_MAP.containsKey(forme)) {
            Class<? extends Etincelle> clz = ETINCELLE_MAP.get(forme);

            Class[] params = new Class[]{double.class, double.class, Color.class};

            try {
                Constructor ctor = clz.getConstructor(params);

                liste.add((Drawable) ctor.newInstance(xf, yf, couleur));

                for (int k = 1; k <= puissEtincelles; k++) {
                    int mult = 10 * k;
                    liste.add((Drawable) ctor.newInstance(xf + mult, yf, couleur));
                    liste.add((Drawable) ctor.newInstance(xf - mult, yf, couleur));
                    liste.add((Drawable) ctor.newInstance(xf, yf + mult, couleur));
                    liste.add((Drawable) ctor.newInstance(xf, yf - mult, couleur));
                    liste.add((Drawable) ctor.newInstance(xf + mult, yf + mult, couleur));
                    liste.add((Drawable) ctor.newInstance(xf + mult, yf - mult, couleur));
                    liste.add((Drawable) ctor.newInstance(xf - mult, yf + mult, couleur));
                    liste.add((Drawable) ctor.newInstance(xf - mult, yf - mult, couleur));
                }

            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
                e.printStackTrace();
            }
        } else {
            System.err.printf("Forme \"%s\" is not supported\n", forme);
        }

        return liste;
    }

    @Override
    protected void peindreEtincelle(Graphics g) {

        LinkedList<Drawable> liste;

        int mult = 10 * size;

        for (int gen = 0; gen < size; gen++) {

//            clearGraphics(g, (int) x - mult, (int) y - mult, 2 * mult, 2 * mult, Color.black);

            liste = getPattern(x, y, couleur, forme, gen);

            if (gen == 0) {
                Drawable d = liste.get(0);
                d.drawOn(g);
            } else {

                for (int i = 0; i < liste.size(); i++) {
                    Drawable d = liste.get(i);
                    if (i >= 8 * (gen - 1) + 1 && i <= 8 * gen) {
                        d.drawOn(g);
                    }
                    // else {
                    //    g.setColor(Color.black);
                    //    ((Etincelle) d).peindreEtincelle(g);
                    // }
                }

                try {
                    Thread.sleep(duree);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

//        clearGraphics(g, (int) x - mult, (int) y - mult, 2 * mult, 2 * mult, Color.black);
    }

    private void clearGraphics(Graphics g, int x, int y, int width, int height, Color background) {
        Color prevColor = g.getColor();

        g.setColor(background);
        g.fillRect(x, y, width, height);

        g.setColor(prevColor);
    }
}

第5步 - 定义用于绘制这些Drawables

的面板
public class FuseePanel extends Panel {

    //CONSTRUCTOR
    public FuseePanel() { }

    //METHOD
    @Override
    public void paint(Graphics g) {
        int w = this.getSize().width;
        int h = this.getSize().height;

        Color defaultColor = g.getColor();
        g.setColor(Color.black);
        g.fillRect(0, 0, w, h);
        g.setColor(defaultColor);

        java.util.List<Drawable> shapes = new ArrayList<Drawable>();
        shapes.add(new PointEtincelle(40, 40));
        shapes.add(new CroixEtincelle(70, 89));

        int fuseeDuree = 100;
        shapes.add(new Fusee(234, 264, PointEtincelle.FORME, Color.blue, 8, 2*fuseeDuree));
        shapes.add(new Fusee(500, 264, CroixEtincelle.FORME, Color.yellow, 20, fuseeDuree/2));
        shapes.add(new Fusee(400, 400, EtoileEtincelle.FORME, Color.red, 8, 5*fuseeDuree));

        for (Drawable d : shapes) {
            d.drawOn(g);
        }
    }

    //MAIN
    public static void main(String[] args) {

        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                final Frame f = new Frame();
                f.setLocation(100, 100);
                f.add(new FuseePanel());
                f.setSize(1200, 700);

                f.addWindowListener(new WindowAdapter() {
                    @Override
                    public void windowClosing(WindowEvent e) {
                        super.windowClosing(e);
                        f.dispose();
                        System.exit(0);
                    }
                });

                f.setVisible(true);
            }
        });
    }
}