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

多线程调用repaint方法无效

请大家帮忙看一下
按照在线程中只改变一个已经声明的面板用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:55
    关注

    是这样的 ,重绘 repaint 方法会调用 Game 的 paint 方法的,断点调试了下,其实是一直都在调用 paint 方法的,但是由于GamePanel 的坐标并没有变动,所以没有重绘。调整下代码,每次重绘之前修改对应的坐标值:
    (内部类 GamePanel 的x 轴坐标跟外部 Game 的坐标是各自独立的属性,需要单独操作的。

    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.setRabbitX(rabbitX);
                    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 ;
                    g2.setTortoiseX(tortoiseX);
                    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 int getRabbitX() {
            return rabbitX;
        }
    
    
        public void setRabbitX(int rabbitX) {
            this.rabbitX = rabbitX;
        }
    
    
        public int getRabbitY() {
            return rabbitY;
        }
    
    
        public void setRabbitY(int rabbitY) {
            this.rabbitY = rabbitY;
        }
    
    
        public int getTortoiseX() {
            return tortoiseX;
        }
    
    
        public void setTortoiseX(int tortoiseX) {
            this.tortoiseX = tortoiseX;
        }
    
    
        public int getTortoiseY() {
            return tortoiseY;
        }
    
    
        public void setTortoiseY(int tortoiseY) {
            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);
            }
    
    }
    

    运行结果如下:
    图片说明

    这种效果是因为上次父组件中绘图遗留导致的,你注释掉的这句
    super.paint(g); //百度说这句可以刷新整个面板
    加上就能重绘整个面板,就只看到一个点在移动了。

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

报告相同问题?

悬赏问题

  • ¥17 pro*C预编译“闪回查询”报错SCN不能识别
  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向