在java中使用线程实现runnable时,形状没有移动
我有一段代码,当实现runnable类时,椭圆形应该自动向右移动。然而,它似乎没有移动。非常感谢您的帮助。提前谢谢在java中使用线程实现runnable时,形状没有移动,java,multithreading,swing,awt,Java,Multithreading,Swing,Awt,我有一段代码,当实现runnable类时,椭圆形应该自动向右移动。然而,它似乎没有移动。非常感谢您的帮助。提前谢谢 package movingball; import java.awt.Color; import java.awt.Graphics; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JFrame; import javax.swing.JPanel; pu
package movingball;
import java.awt.Color;
import java.awt.Graphics;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MovingBall extends JPanel{
private static final int x = 30;
private static final int y = 30;
public MovingBall(){
setBackground(Color.BLACK);
}
public MovingBall(int x, int y){
x = this.x;
y = this.y;
repaint();
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,700);
MovingBall movingBall = new MovingBall();
frame.add(movingBall);
frame.setVisible(true);
调用线程以指定ball对象
BallUsingThread ball = new BallUsingThread(x, y);
Thread first = new Thread(ball);
first.start();
}
@Override
public void paintComponent(Graphics canvas){
super.paintComponent(canvas);
canvas.setColor(Color.BLUE);
canvas.fillOval(x, y, 100, 100);
}
}
/*Here is the second class. Where the oval shape should be moving. Any `suggestions here? Also just let me know if there are some codes need to be adjusted.*/
class BallUsingThread implements Runnable{
int x = 30;
int y = 30;
public BallUsingThread(int x, int y){
this.x = x;
this.y = y;
}
@Override
public void run() {
for(;;){
x++;
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
System.out.printf("Error",ex);
}
}
}
}
您的线程只需更新程序内存(在每个阶段它都会递增
x
)。windowing子系统不知道组件的脏状态,因此不会调用paint方法
您必须调用JComponent.repaint()
,请注意,调用必须在UI线程中进行(例如,通过使用SwingUtilities.invokeLater()
)
请注意,以这种方式,您的程序没有任何机会平稳运行,并且会导致大量CPU周期的中断。对于动画和/或游戏,您需要一个活套,它可以让您在一秒钟内控制帧的运行时间和帧数。您的线程只需更新程序内存(在每个阶段它都会增加
x
)。windowing子系统不知道组件的脏状态,因此不会调用paint方法
您必须调用JComponent.repaint()
,请注意,调用必须在UI线程中进行(例如,通过使用SwingUtilities.invokeLater()
)
请注意,以这种方式,您的程序没有任何机会平稳运行,并且会导致大量CPU周期的中断。对于动画和/或游戏,您需要一个活套,它可以让您在一秒钟内控制帧的运行时间和帧数。这
private static final int x = 30;
private static final int y = 30;
class BallUsingThread implements Runnable{
int x = 30;
int y = 30;
public BallUsingThread(int x, int y){
this.x = x;
this.y = y;
}
@Override
public void run() {
for(;;){
x++;
使值不变
这个
private static final int x = 30;
private static final int y = 30;
class BallUsingThread implements Runnable{
int x = 30;
int y = 30;
public BallUsingThread(int x, int y){
this.x = x;
this.y = y;
}
@Override
public void run() {
for(;;){
x++;
是个毫无意义的人。由于Java传递变量的方式,对值x
的任何修改只会在ball的上下文中使用read
类进行,MovingBall
将看不到它们,即使您可以让它重新绘制
相反,您可能应该将MovingBall
的引用传递给ballusingtread
,并提供一个ballusingtread
调用的方法,该方法更新球的x
位置,例如
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MovingBall extends JPanel {
private int ballX = 30;
private int ballY = 30;
public MovingBall() {
setBackground(Color.BLACK);
}
public MovingBall(int x, int y) {
x = this.ballX;
y = this.ballY;
repaint();
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 700);
MovingBall movingBall = new MovingBall();
frame.add(movingBall);
frame.setVisible(true);
BallUsingThread ball = new BallUsingThread(movingBall);
Thread first = new Thread(ball);
first.start();
}
@Override
public void paintComponent(Graphics canvas) {
super.paintComponent(canvas);
canvas.setColor(Color.BLUE);
canvas.fillOval(ballX, ballY, 100, 100);
}
public void updateBall() {
if (EventQueue.isDispatchThread()) {
ballX++;
repaint();
} else {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
updateBall();
}
});
}
}
}
/*Here is the second class. Where the oval shape should be moving. Any `suggestions here? Also just let me know if there are some codes need to be adjusted.*/
class BallUsingThread implements Runnable {
private MovingBall movingBall;
public BallUsingThread(MovingBall mb) {
movingBall = mb;
}
@Override
public void run() {
for (;;) {
movingBall.updateBall();
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
System.out.printf("Error", ex);
}
}
}
}
现在,Swing不是线程安全的(我已经说明了这一点),但是有一个更简单的解决方案
改用Swing定时器
MovingBall
BallUsingTimer
有关更多详细信息,请参见和
private static final int x = 30;
private static final int y = 30;
class BallUsingThread implements Runnable{
int x = 30;
int y = 30;
public BallUsingThread(int x, int y){
this.x = x;
this.y = y;
}
@Override
public void run() {
for(;;){
x++;
使值不变
这个
private static final int x = 30;
private static final int y = 30;
class BallUsingThread implements Runnable{
int x = 30;
int y = 30;
public BallUsingThread(int x, int y){
this.x = x;
this.y = y;
}
@Override
public void run() {
for(;;){
x++;
是个毫无意义的人。由于Java传递变量的方式,对值x
的任何修改只会在ball的上下文中使用read
类进行,MovingBall
将看不到它们,即使您可以让它重新绘制
相反,您可能应该将MovingBall
的引用传递给ballusingtread
,并提供一个ballusingtread
调用的方法,该方法更新球的x
位置,例如
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MovingBall extends JPanel {
private int ballX = 30;
private int ballY = 30;
public MovingBall() {
setBackground(Color.BLACK);
}
public MovingBall(int x, int y) {
x = this.ballX;
y = this.ballY;
repaint();
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 700);
MovingBall movingBall = new MovingBall();
frame.add(movingBall);
frame.setVisible(true);
BallUsingThread ball = new BallUsingThread(movingBall);
Thread first = new Thread(ball);
first.start();
}
@Override
public void paintComponent(Graphics canvas) {
super.paintComponent(canvas);
canvas.setColor(Color.BLUE);
canvas.fillOval(ballX, ballY, 100, 100);
}
public void updateBall() {
if (EventQueue.isDispatchThread()) {
ballX++;
repaint();
} else {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
updateBall();
}
});
}
}
}
/*Here is the second class. Where the oval shape should be moving. Any `suggestions here? Also just let me know if there are some codes need to be adjusted.*/
class BallUsingThread implements Runnable {
private MovingBall movingBall;
public BallUsingThread(MovingBall mb) {
movingBall = mb;
}
@Override
public void run() {
for (;;) {
movingBall.updateBall();
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
System.out.printf("Error", ex);
}
}
}
}
现在,Swing不是线程安全的(我已经说明了这一点),但是有一个更简单的解决方案
改用Swing定时器
MovingBall
BallUsingTimer
查看和了解更多详细信息
repaint
实际上是少数线程安全方法中的一种,但是MovingBall
将永远看不到ballUsingRead
对x
所做的更改,因此它无论如何都是毫无意义的。我不知道。感谢repaint
实际上是为数不多的线程安全方法之一,但是MovingBall
将永远看不到ballusingtread
对x
所做的更改,所以它无论如何都是毫无意义的。谢谢