学习中的owl 2019-06-07 19:00 采纳率: 85.7%
浏览 243
已采纳

java龟兔赛跑中关于线程调用repaint无效

参照了
https://bbs.csdn.net/topics/390752602

按照在线程中只改变一个已经声明的面板用repaint方法使小圆点移动的想法
进行编写编译器没有报错但是画面仍是没有改变。

java初学,大部分是按书敲的GUI和repaint( ) 方法是自己加的

求大佬帮帮忙

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Game extends JFrame{
    static int BeginX=50,EndX=450;
    static int rabbitX=BeginX,rabbitY=100; //定义兔子的移动坐标
    static int tortoiseX=BeginX,tortoiseY=300;//定以乌龟的移动坐标

    static GamePanel gPanel = new GamePanel(rabbitX,rabbitY,tortoiseX,tortoiseY); 
    //将画面面板初始化
    public Game(){
        this.add(gPanel);//加入画面面板
        this.setTitle("龟兔赛跑");
        this.setSize(800,680);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
        Race race = new Race();
        race.setDistance(100);//声明比赛的长度
        Racer r = new Rabbit("兔子",5,gPanel);//声明一个兔子选手
        Racer t = new Tortoise("乌龟",1,gPanel);//声明一个乌龟选手
        r.attend(race);//将兔子加入选手列表
        t.attend(race);//将乌龟加入选手列表
        race.start();//启动线程
    }

    public static void main(String[] args) {
        new Game();//初始化画面
    }


    class Racer extends Thread{//选手类
            String name;
            Race race;
            int speed;
            int dis =0;//移动的距离
            int isEnd =0;//判断是否结束
            Racer(String name,int speed){
                this.name = name;
                this.speed = speed;
            }
            public void run() {

            }
            public void attend(Race r) {
                race = r;
                r.addRacer(this);
            }
    }
    class Rabbit extends Racer{//兔子选手
        boolean isSleep = false;
        GamePanel g1;
        Rabbit(String name, int speed,GamePanel g1) {
            super(name, speed);
            this.g1 = g1;//将Game类中声明的面板传入
        }
        public void run() {
            while(dis<=race.getDistance()) {
                dis += this.speed;
                //System.out.println("兔纸走了"+dis+"米");
            try {
                Thread.sleep(1000);
                rabbitX += (speed*4);
                g1.repaint();//重绘画面但是无效

            } catch (InterruptedException e) {
                 e.printStackTrace();
            }
            sleepy();
            if(dis==race.getDistance()) {
                isEnd=1;
            }
        }

    }
        public void sleepy() {//兔子睡觉50%的几率,一场比赛最多睡一次
            if(!isSleep) {
                int flag = (int)(Math.random()*2);
                if(flag==1) { //兔子要睡觉了
                    System.out.println("----------兔子要睡觉了-----------");
                    int sleepTime = (int)(Math.random()*61+60);
                    try {
                        Thread.sleep(sleepTime*1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                System.out.println(sleepTime+"----------兔子睡醒了-------------");
                isSleep = true;
            }
        }
      }        
    }
    class Tortoise extends Racer{//乌龟选手类
        GamePanel g2;
        Tortoise(String name, int speed,GamePanel g2) {
            super(name, speed);
            this.g2 = g2;//传入Game类声明的面板
        }
        public void run() {
            while(dis<=race.getDistance()) {
                tortoiseX += (speed*4);
                dis +=speed ;
                System.out.println("乌龟走了"+dis+"米");
            try {
                Thread.sleep(1000);                 
                g2.repaint();//重绘但无效
            } catch (InterruptedException e) {
                    e.printStackTrace();
            }
            if(dis==race.getDistance()) {
                isEnd =2;

            }
         }
       }
      }
     class Race{//比赛类
        private int distance;//比赛距离
        private ArrayList<Racer> racers= new ArrayList<Racer>();//比赛选手列表
        public float getDistance() {
            return distance;
        }
        public void setDistance(int distance) {
            this.distance = distance;
        }
        public ArrayList<Racer> getRacers() {
            return racers;
        }
        public void setRacers(ArrayList<Racer> racers) {
            this.racers = racers;
        } 

        //注册一个参赛者
        public void addRacer(Racer racer) {
            racers.add(racer);
        }
        public void  start() {
            for(Racer racer:racers) {
            racer.start();
           }
         }
        }

}
class GamePanel extends JPanel{//画面面板
    int rabbitX,rabbitY,tortoiseX,tortoiseY;
    GamePanel(int rabbitX,int rabbitY,int tortoiseX,int tortoiseY){
        this.rabbitX = rabbitX;
        this.rabbitY = rabbitY;
        this.tortoiseX = tortoiseX;
        this.tortoiseY = tortoiseY;
    }
    public void paint(Graphics g) {
            //super.paint(g); //百度说这句可以刷新整个面板
            g.setColor(Color.RED);
            g.fillOval(rabbitX, rabbitY, 15, 15);
            g.setColor(Color.BLACK);
            g.fillOval(tortoiseX, tortoiseY ,15,15);
            g.drawLine(600, 100, 600, 350);
            g.drawString("终", 600, 120);
            g.drawString("点", 600, 220);
            g.drawString("线", 600,320);
        }

}
  • 写回答

1条回答 默认 最新

  • 毕小宝 博客专家认证 2019-06-08 20:59
    关注

    GamePanel 的绘图方法使用的坐标是自己的,并没有发生变化,所以看起来外部表现并没有变化,单实际上重绘方法是被调用了的。
    解决办法,可以将 Game 中的两个坐标值定义为public static 的,同时 GamePanel 中不要rabbitX和tortoiseX,使用全局的。
    另一种就是为 GamePanel 中不要rabbitX和tortoiseX提供 set 方法,在调用重绘之前 set 下坐标就好了。

    此外,需要刷新整个容器 super.paint(g); //百度说这句可以刷新整个面板
    加上就能重绘整个面板,就只看到一个点在移动了。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥188 寻找能做王者评分提取的
  • ¥15 matlab用simulink求解一个二阶微分方程,要求截图
  • ¥30 乘子法解约束最优化问题的matlab代码文件,最好有matlab代码文件
  • ¥15 写论文,需要数据支撑
  • ¥15 identifier of an instance of 类 was altered from xx to xx错误
  • ¥100 反编译微信小游戏求指导
  • ¥15 docker模式webrtc-streamer 无法播放公网rtsp
  • ¥15 学不会递归,理解不了汉诺塔参数变化
  • ¥15 基于图神经网络的COVID-19药物筛选研究
  • ¥30 软件自定义无线电该怎样使用