Java 为什么线程在actionListener实现中冻结我的代码?

Java 为什么线程在actionListener实现中冻结我的代码?,java,multithreading,swing,try-catch,actionlistener,Java,Multithreading,Swing,Try Catch,Actionlistener,我试着通过点击按钮(向上,向下,…)来平滑地移动椭圆,我试着使用线程来尝试捕捉它在类内的工作,但当我在这里使用它时,它会冻结整个应用程序 class movingdown implements ActionListener{ @Override public void actionPerformed(ActionEvent e){ for (int i = 0; i < frame.getWidth(); i++) { x++;

我试着通过点击按钮(向上,向下,…)来平滑地移动椭圆,我试着使用线程来尝试捕捉它在类内的工作,但当我在这里使用它时,它会冻结整个应用程序

class movingdown implements ActionListener{
    @Override 
    public void actionPerformed(ActionEvent e){
        for (int i = 0; i < frame.getWidth(); i++) {
            x++;
            frame.repaint();
            try{Thread.sleep(50);}catch(Exception ex){}

        }
    }
}//movingdown end
类向下移动实现ActionListener{
@凌驾
已执行的公共无效操作(操作事件e){
对于(int i=0;i
这是我的全部代码:

package swingWork;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
public class movingball {
JFrame frame;
int x=0;
int y =0;
public static void main(String []args){
    movingball ball = new movingball();
    ball.start();

}
public void start(){
    ballDrawer drawer = new ballDrawer();   
    frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JButton up =new JButton("UP");
    JButton down =new JButton("DOWN");
    JButton left =new JButton("LEFT");
    JButton right =new JButton("RIGHT");

    frame.getContentPane().add(BorderLayout.NORTH, up);
    frame.getContentPane().add(BorderLayout.SOUTH, down);   
    frame.getContentPane().add(BorderLayout.WEST, left);
    frame.getContentPane().add(BorderLayout.EAST, right);
    frame.getContentPane().add(BorderLayout.CENTER,drawer);
    //setting up the action listener:

    up.addActionListener(new movingup());
    down.addActionListener(new movingdown());
    left.addActionListener(new movingleft());
    right.addActionListener(new movingright());
    frame.setSize(300, 300);
    frame.setVisible(true);
int rightsize =right.getWidth();



}//start method end


//here we have the listeners

class movingup implements ActionListener{

    @Override
    public void actionPerformed(ActionEvent e) {
    for (int i = x; i > frame.getHeight(); i--) {
        x=i;
        try{Thread.sleep(50);}catch(Exception ex){}
    }
    }

}//moving up end
class movingdown implements ActionListener{
    @Override 
    public void actionPerformed(ActionEvent e){
        for (int i = 0; i < frame.getWidth(); i++) {
            x++;
            frame.repaint();
            try{Thread.sleep(50);}catch(Exception ex){}

        }
    }
}//movingdown end
class movingleft implements ActionListener{
    public void actionPerformed(ActionEvent e){


            x=x+10;
            frame.repaint();

        System.out.println(x);

    }
}//moving  left end
class movingright implements ActionListener{
    public void actionPerformed(ActionEvent e){

    }
}//moving right end


class ballDrawer extends JPanel{
    @Override
public void paintComponent(Graphics g) {
        g.setColor(Color.white);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());

        g.setColor(Color.black);
        g.fillOval(x, y, 100, 100);


    }//PaintComponents End


}//ball drawer class end

}//main class end
包装欺诈;
导入java.awt.BorderLayout;
导入java.awt.Button;
导入java.awt.Color;
导入java.awt.Graphics;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入javax.swing.*;
公共级运动球{
JFrame框架;
int x=0;
int y=0;
公共静态void main(字符串[]args){
移动球=新的移动球();
ball.start();
}
公开作废开始(){
ballDrawer抽屉=新的ballDrawer();
frame=新的JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton up=新JButton(“up”);
JButton down=新JButton(“down”);
JButton left=新JButton(“左”);
JButton right=新JButton(“right”);
frame.getContentPane().add(BorderLayout.NORTH,向上);
frame.getContentPane().add(BorderLayout.SOUTH,向下);
frame.getContentPane().add(BorderLayout.WEST,左);
frame.getContentPane().add(BorderLayout.EAST,右);
frame.getContentPane().add(BorderLayout.CENTER,drawer);
//设置操作侦听器:
addActionListener(new movingup());
addActionListener(新的movingdown());
addActionListener(新的movingleft());
addActionListener(新的movingright());
框架。设置尺寸(300300);
frame.setVisible(true);
int rightsize=right.getWidth();
}//开始方法结束
//这里有听众
类movingup实现ActionListener{
@凌驾
已执行的公共无效操作(操作事件e){
对于(int i=x;i>frame.getHeight();i--){
x=i;
试试{Thread.sleep(50);}catch(Exception ex){}
}
}
}//上移端
类movingdown实现ActionListener{
@凌驾
已执行的公共无效操作(操作事件e){
对于(int i=0;i
您从未、从未、从未想要在上使用
Thread.sleep()
。曾经 它永远不会完成任何好事,它会让你的屏幕冻结,直到睡眠结束。所以不要这样做

在Swing中设置动画的最佳方法是使用动画来触发定期更改图形特性的事件。这发生在不同的线程上,因此屏幕保持响应。您可以将此计时器设置为一直运行,但当圆圈不应移动时,让它不执行任何操作。下面是
计时器
ActionListener

t = new Timer(TIMER_DELAY, new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent e) {
    if(deltaX == 1 && x >= frame.getWidth() - CIRCLE_WIDTH) deltaX = 0;
    if(deltaY == 1 && y >= frame.getHeight() - CIRCLE_HEIGHT) deltaY = 0;
    if(deltaX == -1 && x <= 0) deltaX = 0;
    if(deltaY == -1 && y <= 0) deltaY = 0;
    x += deltaX;
    y += deltaY;
    if(deltaX != 0 || deltaY != 0) {
      frame.repaint();
    }
  }
});
t.start();
如您所见,我在
start
方法中创建了一个timer对象,并通过按下按钮告诉计时器开始设置动画。计时器有自己的、不同的
ActionListener
(实现为here),它实际告诉参数要更改,然后在有东西移动时重新绘制。您可以通过告诉Swing只重绘屏幕上需要重绘的部分来进一步优化它,但这只是一个示例。如果执行此操作,请确保重新绘制足够大,以获得圆的位置和现在的位置

这是完整的程序,包括常数
圆圈宽度
圆圈高度
,新的计时器逻辑,以及所有四个按钮的更改:

package swingWork;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class movingball {
  private static final int CIRCLE_WIDTH = 100;
  private static final int CIRCLE_HEIGHT = 100;
  private static final int TIMER_DELAY = 50;

  JFrame frame;
  int x = 0;
  int y = 0;
  int deltaX = 0;
  int deltaY = 0;
  Timer t;

  public static void main(String[] args) {
    movingball ball = new movingball();
    ball.start();

  }

  public void start() {
    ballDrawer drawer = new ballDrawer();
    frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JButton up = new JButton("UP");
    JButton down = new JButton("DOWN");
    JButton left = new JButton("LEFT");
    JButton right = new JButton("RIGHT");

    frame.getContentPane().add(BorderLayout.NORTH, up);
    frame.getContentPane().add(BorderLayout.SOUTH, down);
    frame.getContentPane().add(BorderLayout.WEST, left);
    frame.getContentPane().add(BorderLayout.EAST, right);
    frame.getContentPane().add(BorderLayout.CENTER, drawer);
    // setting up the action listener:

    up.addActionListener(new movingup());
    down.addActionListener(new movingdown());
    left.addActionListener(new movingleft());
    right.addActionListener(new movingright());
    frame.setSize(300, 300);
    frame.setVisible(true);
    
    t = new Timer(TIMER_DELAY, new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        if(deltaX == 1 && x == frame.getWidth() - CIRCLE_WIDTH) deltaX = 0;
        if(deltaY == 1 && y == frame.getHeight() - CIRCLE_HEIGHT) deltaY = 0;
        if(deltaX == -1 && x == 0) deltaX = 0;
        if(deltaY == -1 && y == 0) deltaY = 0;
        x += deltaX;
        y += deltaY;
        if(deltaX != 0 || deltaY != 0) {
          frame.repaint();
        }
      }
    });
    t.start();

  }// start method end

  // here we have the listeners

  class movingup implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
      deltaY = -1;
    }
  }// moving up end

  class movingdown implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
      deltaY = 1;
    }
  }// movingdown end

  class movingleft implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
      deltaX = -1;
    }
  }// moving left end

  class movingright implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
      deltaX = 1;
    }
  }// moving right end

  class ballDrawer extends JPanel {
    @Override
    public void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.setColor(Color.white);
      g.fillRect(0, 0, this.getWidth(), this.getHeight());

      g.setColor(Color.black);
      g.fillOval(x, y, CIRCLE_WIDTH, CIRCLE_HEIGHT);

    }// PaintComponents End

  }// ball drawer class end

}// main class endreading: http://stackoverflow.com/q/15511282/1768232
您永远不会想要在上使用
Thread.sleep()
。曾经 它永远不会完成任何好事,它会让你的屏幕冻结,直到睡眠结束。所以不要这样做

在Swing中设置动画的最佳方法是使用动画来触发定期更改图形特性的事件。这发生在不同的线程上,因此屏幕保持响应。您可以将此计时器设置为一直运行,但当圆圈不应移动时,让它不执行任何操作。下面是
计时器
ActionListener

t = new Timer(TIMER_DELAY, new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent e) {
    if(deltaX == 1 && x >= frame.getWidth() - CIRCLE_WIDTH) deltaX = 0;
    if(deltaY == 1 && y >= frame.getHeight() - CIRCLE_HEIGHT) deltaY = 0;
    if(deltaX == -1 && x <= 0) deltaX = 0;
    if(deltaY == -1 && y <= 0) deltaY = 0;
    x += deltaX;
    y += deltaY;
    if(deltaX != 0 || deltaY != 0) {
      frame.repaint();
    }
  }
});
t.start();
如您所见,我在
start
方法中创建了一个timer对象,并通过按下按钮告诉计时器开始设置动画。计时器有自己的、不同的
ActionListener
(实现为here),它实际告诉参数要更改,然后在有东西移动时重新绘制。您可以通过告诉Swing只重绘屏幕上需要重绘的部分来进一步优化它,但这只是一个示例。如果执行此操作,请确保重新绘制足够大,以获得圆的位置和现在的位置

这是完整的程序,包括常数
圆圈宽度
圆圈高度
,新的计时器逻辑,以及所有四个按钮的更改:

package swingWork;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class movingball {
  private static final int CIRCLE_WIDTH = 100;
  private static final int CIRCLE_HEIGHT = 100;
  private static final int TIMER_DELAY = 50;

  JFrame frame;
  int x = 0;
  int y = 0;
  int deltaX = 0;
  int deltaY = 0;
  Timer t;

  public static void main(String[] args) {
    movingball ball = new movingball();
    ball.start();

  }

  public void start() {
    ballDrawer drawer = new ballDrawer();
    frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JButton up = new JButton("UP");
    JButton down = new JButton("DOWN");
    JButton left = new JButton("LEFT");
    JButton right = new JButton("RIGHT");

    frame.getContentPane().add(BorderLayout.NORTH, up);
    frame.getContentPane().add(BorderLayout.SOUTH, down);
    frame.getContentPane().add(BorderLayout.WEST, left);
    frame.getContentPane().add(BorderLayout.EAST, right);
    frame.getContentPane().add(BorderLayout.CENTER, drawer);
    // setting up the action listener:

    up.addActionListener(new movingup());
    down.addActionListener(new movingdown());
    left.addActionListener(new movingleft());
    right.addActionListener(new movingright());
    frame.setSize(300, 300);
    frame.setVisible(true);
    
    t = new Timer(TIMER_DELAY, new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        if(deltaX == 1 && x == frame.getWidth() - CIRCLE_WIDTH) deltaX = 0;
        if(deltaY == 1 && y == frame.getHeight() - CIRCLE_HEIGHT) deltaY = 0;
        if(deltaX == -1 && x == 0) deltaX = 0;
        if(deltaY == -1 && y == 0) deltaY = 0;
        x += deltaX;
        y += deltaY;
        if(deltaX != 0 || deltaY != 0) {
          frame.repaint();
        }
      }
    });
    t.start();

  }// start method end

  // here we have the listeners

  class movingup implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
      deltaY = -1;
    }
  }// moving up end

  class movingdown implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
      deltaY = 1;
    }
  }// movingdown end

  class movingleft implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
      deltaX = -1;
    }
  }// moving left end

  class movingright implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
      deltaX = 1;
    }
  }// moving right end

  class ballDrawer extends JPanel {
    @Override
    public void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.setColor(Color.white);
      g.fillRect(0, 0, this.getWidth(), this.getHeight());

      g.setColor(Color.black);
      g.fillOval(x, y, CIRCLE_WIDTH, CIRCLE_HEIGHT);

    }// PaintComponents End

  }// ball drawer class end

}// main class endreading: http://stackoverflow.com/q/15511282/1768232

for循环造成了很大的滞后。尝试像这样重新构造代码

public class MovingBall{
    String direction;
    int x=0;
    int y=0;

    public static void main(String[] args){
        //create your frame and buttons...
        upButton.addActionListener(new ActionListener{
            direction = "up";
        });
        //repeat this actionListener to the other buttons
        while (true){
            try{Thread.sleep(50);}catch(Exception e){e.printStackTrace();}
            drawer.repaint();
        }
    }
    public class Drawer extends JPanel{
        public void paint(Graphics g){
            if(direction.equals("up")) {
                y = y - 5;
            }
            //repeat the if statement with the other directions
            g.setColor(Color.white);
            g.fillRect(0,0,frame.getWidth(),frame.getHeight());
            g.setColor(Color.black);
            g.fillOval(x,y,100,100);
        }
    }
}

for循环造成了很大的滞后。尝试像这样重新构造代码

public class MovingBall{
    String direction;
    int x=0;
    int y=0;

    public static void main(String[] args){
        //create your frame and buttons...
        upButton.addActionListener(new ActionListener{
            direction = "up";
        });
        //repeat this actionListener to the other buttons
        while (true){
            try{Thread.sleep(50);}catch(Exception e){e.printStackTrace();}
            drawer.repaint();
        }
    }
    public class Drawer extends JPanel{
        public void paint(Graphics g){
            if(direction.equals("up")) {
                y = y - 5;
            }
            //repeat the if statement with the other directions
            g.setColor(Color.white);
            g.fillRect(0,0,frame.getWidth(),frame.getHeight());
            g.setColor(Color.black);
            g.fillOval(x,y,100,100);
        }
    }
}

正如已经指出的,你是b