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