I am trying to move a ball in applet using thread but its not moving

霸气de小男生 提交于 2020-01-21 18:39:04

问题


I am trying to move a ball in applet using thread but its not moving. Can anyone help me out as m new to applet and proceeding for game development..for reference here is my code

public class ballGame extends JApplet implements Runnable
{
    int x_pos=50;
    int y_pos=100;
    int rad=10;
    Thread t;

    public void start() 
    {
        super.start();
        t=new Thread("t");
        t.start();
    }

    public void paint(Graphics g) 
    {
        super.paint(g);
        g.setColor(Color.red);
        setBackground(Color.BLACK);
        g.drawOval(x_pos,y_pos,2*rad,2*rad); 

        while(true)
        {
            x_pos++;

            //validate();
            repaint();

            try
            {
                Thread.sleep(100);
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }

        }//end of while
    }//end of paint()
}

回答1:


Swing is a single thread environment. That is, all updates and interactions are executed within a single thread. Swing is also NOT thread safe. This means that all updates to the UI MUST be executed within the context of that thread (the Event Dispatching Thread or ETD).

Any code that blocks the EDT will prevent it from (amongst other things), repainting the UI and responding to input from the user.

You're paint code will NEVER update the screen, in fact it will make your application appear to "hang", as the paint method isn't being allowed to complete and is blocking the ETD.

It is an exception that the paint method will return quickly after been called and may be called repeatedly in quick succession.

Generally speaking, a Thread is probably a little over kill, something like a javax.swing.Timer would be more then suitable under these circumstances.

public class AnimatedBoat {

    public static void main(String[] args) {
        new AnimatedBoat();
    }

    public AnimatedBoat() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new AnimationPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class AnimationPane extends JPanel {

        private BufferedImage boat;
        private int xPos = 0;
        private int direction = 1;

        public AnimationPane() {
            try {
                boat = ImageIO.read(new File("boat.png"));
                Timer timer = new Timer(40, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        xPos += direction;
                        if (xPos + boat.getWidth() > getWidth()) {
                            xPos = getWidth() - boat.getWidth();
                            direction *= -1;
                        } else if (xPos < 0) {
                            xPos = 0;
                            direction *= -1;
                        }
                        repaint();
                    }

                });
                timer.setRepeats(true);
                timer.setCoalesce(true);
                timer.start();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return boat == null ? super.getPreferredSize() : new Dimension(boat.getWidth() * 4, boat.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            int y = getHeight() - boat.getHeight();
            g.drawImage(boat, xPos, y, this);

        }

    }

}

As a side note. You should rarely need to override the paint method of a top level container like JApplet or JFrame, while there are a number of good reasons for this, the one that you're going to most interested in is the fact that they're not double buffered, meaning you are likely to see flickering as the screen is updated.

It's better to use something like JPanel and override it's paintComponent method instead.

Take a look at

  • Performing Custom Painting
  • Concurrency in Swing
  • Painting in AWT and Swing

For more information

nb While I've used a JFrame for my example, it would be a simple matter to take the animation panel and put it into a JApplet, this is another reasons why you don't need/want to extend from top level containers ;)




回答2:


Having an infinite loop in paint means that not a single pass of the method can complete.

Also you should never call Thread.sleep(100) in the paint method. This blocks the EDT and degrades performance.

Instead use a Swing Timer to do the update and repainting work. Also I would sub-class a JComponent and override paintComponent.




回答3:


You can not invoke repaint() method inside paint(). And you can not organize infinitely loop inside paint() method - doing so, you are blocking drawing in your applet.




回答4:


x_posis an int value, thus it is passed to methods by value, not by reference. That is why, when you change its value, the value inside of your circle is not updated...




回答5:


You create a Thread without a run() method. This method should contain the runnable code... Furthermore, the paint() method is to paint stuff, not update stuff!

So move your while loop from the paint() method into the run() method of your thread:

t=new Thread("t") {
    @Override
    public void run()
    {
        while(true)
        {
            x_pos++;

            //validate();
            repaint();

            try
            {
                Thread.sleep(100);
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }//end of while
    }
};

Note that ballGame does not require the implement Runnable part. As the thread you created will provide it.




回答6:


Have the while loop inside the run method of Runnable.

UPDATE:

Have this in the start method.

t=new Thread(this);
t.start();


来源:https://stackoverflow.com/questions/14456072/i-am-trying-to-move-a-ball-in-applet-using-thread-but-its-not-moving

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!