Java Simple Bouncing Ball, SingleThread, Mouse Listener, JFrame

Я создал приложение Bouncing Ball на Java. Цель состоит в том, чтобы мяч появился на mousePressed() и отскочил от стен, не выходя из кадра. Только один мяч, одна нить, должно быть легко. Моя проблема в том, что каждый раз, когда я нажимаю, чтобы появился мяч, он становится быстрее, и я понятия не имею, почему. Может кто-нибудь помочь мне, пожалуйста. PS: я новичок в тредах.

import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MyFrame extends JPanel {
public int xPos, yPos, xDir = 3, yDir = 4;
public int diameter = 50;

public MyFrame(){
    final JFrame thisFrame = new JFrame();
    thisFrame.add(this);
    thisFrame.setTitle("Bouncing Ball");
    thisFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    thisFrame.setLocationRelativeTo(null);
    thisFrame.setSize(500, 500);

    this.addMouseListener(new MouseListener() {
        @Override
        public void mouseReleased(MouseEvent e) {}
        @Override
        public void mousePressed(MouseEvent e) {
            xPos = e.getX();
            yPos = e.getY();
            Thread t = new Thread() {
                @Override
                public void run() {
                    while(true){
                        try{
                            Thread.sleep(10);
                        }catch(Exception e){};
                        xPos += xDir;
                        yPos += yDir;

                        if(xPos + diameter >= thisFrame.getWidth() - 25 || xPos <= 0) xDir = -xDir;
                        if(yPos + diameter >= thisFrame.getHeight() - diameter || yPos <= 0) yDir = -yDir;
                        repaint();
                    }
                } 
            };
            t.start();
        }
        @Override
        public void mouseExited(MouseEvent e) {}
        @Override
        public void mouseEntered(MouseEvent e) {}
        @Override
        public void mouseClicked(MouseEvent e) {}
        });

    thisFrame.setVisible(true);

    }
    public void paintComponent(Graphics g) { 
        super.paintComponent(g); 
        g.fillOval(xPos, yPos, diameter, diameter); 
    }
}
public class MyMain{

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

}

person Matz0rz    schedule 17.01.2014    source источник
comment
Используйте MouseAdapter в будущем, когда вам не нужно переопределять каждый метод события мыши.   -  person Tom Cammann    schedule 18.01.2014


Ответы (1)


Каждый раз, когда вы щелкаете, вы запускаете новый поток, что означает, что у вас есть другой поток, обновляющий позиции x/y.

Например, 1 поток означает, что вы обновляете x/p один раз за синхронизацию, 2 означает, что вы обновляете положение x/y минимум два раза за цикл, и это просто усугубляется каждый раз, когда вы добавляете новый нить.

Лучшим решением было бы начать Thread на некоторое время раньше, а затем использовать List для сохранения положения и направления мяча.

Это потребует небольшой синхронизации, чтобы все было в безопасности.

К вашему сведению, задержка в 40 миллисекунд составляет примерно 25 кадров в секунду, а 16 миллисекунд — это примерно 60 кадров в секунду. ИМХО, для того, что вы делаете, 10 миллисекунд кажутся чрезмерными...

person MadProgrammer    schedule 17.01.2014
comment
Если я правильно понимаю, каждый раз, когда я нажимаю, предыдущий поток не умирает. В результате несколько потоков...? Извините, если я немного запутался. Вы говорите, что я должен инициализировать поток вне нажатия мыши и запустить его при нажатии мыши? Если это так, не должен ли я прекратить его, прежде чем запускать его снова? Спасибо за вашу помощь. - person Matz0rz; 18.01.2014
comment
Да первой части. Вторая часть будет зависеть от того, что вы хотите сделать. Если вы хотите только один мяч, то. Вы можете просто сбросить положение x/y и не беспокоиться ни о чем другом. Если вы хотите больше мячей, вам нужно использовать какой-то список для хранения информации, необходимой для управления каждым мячом. - person MadProgrammer; 18.01.2014
comment
Я также должен отметить, что javax.swing.Timer будет проще в управлении и безопаснее с точки зрения обновления. - person MadProgrammer; 18.01.2014
comment
Я исправил это, чувак, большое спасибо. Я собираюсь протестировать его и опубликовать обновленный код через минуту. Еще раз спасибо за помощь. - person Matz0rz; 18.01.2014
comment
Хорошо, я опубликую это завтра, потому что у меня недостаточно репутации, чтобы ответить на мой собственный вопрос. QQ. - person Matz0rz; 18.01.2014