java - 在java中使用线程实现runnable时,形状不移动

标签 java multithreading swing awt

我有这段代码,在实现可运行类时,椭圆形应自动移动到右侧。然而它似乎没有动。任何帮助深表感谢。提前致谢。

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);

调用线程分配球对象

        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);
                }
            }
        }

    }

最佳答案

这个...

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 的任何修改都只能在 BallUsingThread 类的上下文中进行,而 MovingBall 则不会看到它们,即使你可以重新粉刷它。

相反,您可能应该将 MovingBall 的引用传递给 BallUsingThread 并提供 BallUsingThread 调用的方法来更新 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 Timer...

移动球

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

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);

        BallUsingTimer ball = new BallUsingTimer(movingBall);
        Timer timer = new Timer(40, ball);
        timer.start();
    }

    @Override
    public void paintComponent(Graphics canvas) {
        super.paintComponent(canvas);

        canvas.setColor(Color.BLUE);
        canvas.fillOval(ballX, ballY, 100, 100);
    }

    public void updateBall() {
        ballX++;
        repaint();
    }

}

BallUsingTimer

public class BallUsingTimer implements ActionListener {

    private MovingBall movingBall;

    public BallUsingTimer(MovingBall mb) {
        movingBall = mb;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        movingBall.updateBall();
    }

}

参见Concurrency in SwingHow to use Swing Timers了解更多详情

关于java - 在java中使用线程实现runnable时,形状不移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35667811/

相关文章:

java - Google 表格列数

c++ - Thread std::invoke unknown type and failed to specialize function 错误

java - GridBagLayout 将所有对象放在同一个单元格中

java - 图像未出现在小程序中

java - 服务器实例未配置 : java. lang.ClassNotFoundException :org. apache.catalina.startup.VersionLoggerListener

java - 数组相乘时遇到问题

c# - 捕获的异常如何为 null(不是 NullReferenceException)?

java - 另一个线程进入互斥体

java - 使用 JFrame 在 JPanel 之间切换

java - 获取 JTextPane 内容的高度