Использование awt Paint в многопоточности

У меня есть школьный проект, и я хочу посвятить его Новому году, проект, который я придумал, это текстовый фейерверк, я использую символы и символы в качестве частиц взрыва, и просто постоянно меняю их положение X и Y внутри Paint( ). Я не понимаю, как использовать Paint и Thread вместе. Проблема в том, что он не рисует на экране или, возможно, поток не запускается. (не могу точно сказать, извините). проблема в том, что я не получаю никаких ошибок, это просто не работает :(

код немного длинный, я думаю, спасибо, что прочитали его.

Как это должно работать: когда пользователь щелкает, поток Firework будет запущен в позиции мыши, этот класс Firework имеет цикл рисования для воссоздания добавочного взрыва. в общем, я хочу, чтобы пользователь создавал несколько взрывов, поэтому я сделал это потоком.

вот основной апплет:

public class TBFireworks extends Applet implements MouseListener
{
    public void init()
    {
        setBackground( Color.black );
        addMouseListener( this );
    }

    public void mouseEntered( MouseEvent e ) { }
    public void mouseExited( MouseEvent e ) { }
    public void mousePressed( MouseEvent e ) { }
    public void mouseReleased( MouseEvent e ) { }
    public void mouseClicked( MouseEvent e ) 
    {
        new Firework( e.getX(),e.getY(), this);
    }
}

и класс Firework Thread:

class Firework extends Thread
{
    Point center = new Point(0,0);
    int blastRadius = 10;
    Point posIncrement = new Point(0,0);
    Applet applet;

    public Firework(int positionX, int positionY, Applet apple)
    {
        center.x = positionX;
        center.y = positionY;
        applet = apple;
        new Thread(this).start();
    }

    public void run()
    {
        while(blastRadius > 0)
        {
            applet.paint(applet.getGraphics());

            try {
                this.sleep(1000/20);
            } catch (InterruptedException e) { ; }
        }
    }

    public void paint(Graphics g)
    {
        if(blastRadius > 0)
        {
            Point[] fakeFire = {new Point(20,20),new Point(20,30),new Point(30,20)};
            ApplyNextPos(fakeFire,posIncrement);

            g.setColor(Color.red);
            for(int xaa=1; xaa<5; xaa++) // draw the formation
            {
                for(int zaa=0;zaa<fakeFire.length;zaa++)
                {
                    fakeFire[zaa] = GetQuadrant(xaa,center,fakeFire[zaa]);
                }

                for(int yaa=0;yaa<fakeFire.length;yaa++)
                {
                    g.drawString("*",fakeFire[yaa].x,fakeFire[yaa].y);
                }
            }
            posIncrement.incrementPos(5);
            blastRadius--;
        }
    }
}

person Albert    schedule 17.10.2010    source источник


Ответы (2)


Во-первых, вы, кажется, не используете свой метод рисования в потоке FireWork, вместо этого вы вызываете метод рисования апплета.

Я немного разбираюсь в апплетах и ​​AWT, но если бы это был Swing (думаю, это не так уж и отличается), я бы предложил другой подход. Окрашивание должно (можно?) выполняться только в EDT (потоке отправки событий). Когда пользователь щелкает, вы создаете объект, аналогичный FireWork, и добавляете его в список. Затем вы запускаете ОДИН поток (если он еще не запущен, который постоянно вызывает перерисовку на некоторой панели. Затем в методе рисования вашей панели вы зацикливаете список всех фейерверков и рисуете их.

Это также будет более эффективно использовать память, поскольку вы используете только один поток.

person Avall    schedule 17.10.2010
comment
Спасибо, я сделал Paint() в основном классе, и каждый раз, когда создается экземпляр Firework, он затем помещается в ArrayList, Paint() в основном классе зацикливает все ArrayList для их рисования. Теперь это работает. спасибо! - person Albert; 17.10.2010
comment
Рисовать можно в любом потоке, но это должно быть сделано в EDT. - person Ishtar; 17.10.2010

Метод paint должен (обычно) вызываться графическим интерфейсом только тогда, когда соответствующий компонент или его часть необходимо (пере)рисовать. Он не должен вызываться приложением (если не из другого метода paint).

Метод paint вызывается для отображения фактического состояния компонента. Состояние должно быть изменено другим методом/потоком. Перекрашивание компонента принудительно вызывается repaint.

Неполный, непроверенный пример:

public class Animation extends Canvas {

    private final List<Firework> fireworks = new ArrayList<Firework>(); 

    public void start() {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    step();
                    Thread.sleep(STEP_TIME);  // InterruptedException ?
                }
            }
        });
        t.start();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        for (Firework fw : fireworks)
            fw.draw(g);  // draw the Firework
    }

    private void step() {
        for (Firework fw : fireworks) 
            fw.step();  // update/move the Firework
        repaint();
    }

    // methods for adding/deleting Fireworks, synchronization?
}
person user85421    schedule 17.10.2010