从其他类中的线程调用时不重新出现

时间:2013-10-18 00:41:42

标签: java multithreading swing

我正在尝试制作一个简单的火炮游戏,并在点击按钮时打印一个在圆弧上移动的圆圈。

点击后,我创建一个线程并计算“射弹”的位置,并在计算x和y位置打印出一个圆圈。

当我从一个类执行代码时,它调用重绘并绘制“射弹”的轨迹但是当我设置一个单独的类来调用它并在点击按钮时将其打印出来它不会调用从循环中重新开始。

当我执行下面的类时,它会显示我想要的内容。

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Pong4 extends JPanel implements Runnable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private ScreenLocation location;

    private boolean renderBulit = false;

    public static void main(String[] args)
    {
        Pong4 p = new Pong4();

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(p);
        frame.setSize(800, 600);
        frame.setVisible(true);

        Thread thread = new Thread(p);
        thread.start();
        try {
            thread.join();
        } catch (InterruptedException ex) {
            // TODO Auto-generated catch block
            ex.printStackTrace();
        }
    }

    public Pong4()
    {
    }

    public ScreenLocation updatePosition(ScreenLocation location, double xSpeed, double ySpeed, double time) 
    {   
        return new ScreenLocation((int)(location.getX() + xSpeed * time), (int)(location.getY() - ySpeed * time));
    }


    @Override
    public void run()
    {

        double time = 0;
        location = new ScreenLocation(100, 400);
        renderBulit = true;

        double xSpeed = 50;
        double ySpeed = 50;

        while (location.getX() >= 0 && 800 > location.getX() && 400 >= location.getY())
        {       
            repaint();

            System.out.println("test");

            try {
                Thread.sleep(15);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            time += 0.01;
            location = updatePosition(location, xSpeed, ySpeed, time);
            ySpeed = ySpeed - Constants.GRAVITY * time;
        }

        renderBulit = false;
        repaint();

    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponents(g); 
        Graphics2D g2d = (Graphics2D)g;

        // Paint a gradient from top to bottom
        GradientPaint gp = new GradientPaint( 0, 0, Color.BLACK,
            0, getHeight( ), new Color(0, 0, 255).darker( ).darker() );

        g2d.setPaint( gp );
        g2d.fillRect( 0, 0, getWidth( ), getHeight( ) );

        if (renderBulit)
        {
            // draw circle (color already set to foreground)
            g.setColor(Color.red);
            g.fillOval(location.getX(), location.getY(), 4, 4);
            g.drawOval(location.getX(), location.getY(), 4, 4);


            //Image image = new ImageIcon("src/au/com/tankwarz/view/resources/images/BULIT0.GIF").getImage();
            //g.drawImage(image, location.getX(), location.getY(), this); 
        }
        g2d.dispose();       
    }

    public class ScreenLocation 
    {
        private int x;

        private int y;

        public ScreenLocation (int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public void setX(int x) {
            this.x = x;
        }

        public int getY() {
            return y;
        }

        public void setY(int y) {
            this.y = y;
        }


    }
}

但是,当我尝试以下时,它不会显示。

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

import org.jdesktop.application.Application;

public class Pong3 extends JPanel{

    public static void main(String[] args)
    {

        new Pong3();
    }

    private static final long serialVersionUID = 2944576178447230562L;

    private JButton fireButton;
    private JPanel controlsPanel;

    private Pong4 pong;

    public Pong3() {
        super();
        initGUI();

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(this);
        frame.setSize(800, 600);
        frame.setVisible(true);
    }

    private void initGUI() {
        try {
            this.setPreferredSize(new java.awt.Dimension(800, 600));
            this.setSize(800, 600);
            this.setLayout(null);
            {
                pong = new Pong4();
                this.add(pong);
                pong.setLayout(null);
                pong.setBounds(0, 0, 800, 450);
            }           
            {
                controlsPanel = new JPanel();
                this.add(controlsPanel);
                GridBagLayout controlsPanelLayout = new GridBagLayout();
                controlsPanelLayout.rowWeights = new double[] {0.1, 0.1, 0.1, 0.1};
                controlsPanelLayout.rowHeights = new int[] {7, 7, 7, 7};
                controlsPanelLayout.columnWeights = new double[] {0.1, 0.1, 0.1, 0.1};
                controlsPanelLayout.columnWidths = new int[] {7, 7, 7, 7};
                controlsPanel.setLayout(controlsPanelLayout);
                controlsPanel.setBounds(0, 450, 800, 110);
                controlsPanel.setName("controlsPanel");

                {
                    fireButton = new JButton();
                    controlsPanel.add(fireButton, new GridBagConstraints(3, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
                    fireButton.setName("fireButton");
                    fireButton.setText("Fire");
                    fireButton.setPreferredSize(new java.awt.Dimension(104, 51));
                    fireButton.addActionListener(new ActionListener() {

                        @Override
                        public void actionPerformed(ActionEvent e) {            
                            Thread thread = new Thread(pong);
                            thread.start();
                            try {
                                thread.join();
                            } catch (InterruptedException ex) {
                                // TODO Auto-generated catch block
                                ex.printStackTrace();
                            }


                        }
                    });
                }
            }
            Application.getInstance().getContext().getResourceMap(getClass()).injectComponents(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

感谢任何帮助,为什么这样做。

1 个答案:

答案 0 :(得分:2)

您的thread.join()通过将“后台”线程与当前线程绑定来解除尝试使用后台线程的所有好处,因此您不应该这样做。事情似乎在第一个代码中工作的唯一原因是由于您的代码最初不在事件派发线程中运行,因此您的join()调用将线程连接到主线程而不是EDT,因此不会冻结EDT。无论哪种方式,join()都出错了。

我认为更好的解决方案是使用Swing Timer。这将消除显式使用后台线程的需要。

顺便说一句:如果要创建具有强大,灵活和美观的布局的GUI,请避免使用空布局。