0

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

单击时,我创建一个线程并计算“射弹”的位置并在计算 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();
        }
    }

}

希望有任何帮助说明为什么会这样。

4

1 回答 1

2

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

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

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

于 2013-10-18T00:45:18.830 回答