重绘()只工作了一半

时间:2015-08-14 21:52:20

标签: java multithreading swing applet

我对简单的练习有疑问。 我被要求制作一个小程序,打印出一个绿色的椭圆形(填充),直到它撞到边框,变得更大,而不是开始变小。 这应该继续,直到你关闭小程序。

好吧,我出来了这段代码

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JApplet;

public class Disco extends JApplet{

private int x;
private int y;
private int r;
private boolean enlarge;
MakeLarger makeLarger;
MakeSmaller makeSmaller;

public void init() {}

public void start() {
    x = getWidth()/2;
    y = getHeight()/2;
    r = 50;
    enlarge = true;
    makeLarger = new MakeLarger();
    makeLarger.start();
}

public void paint(Graphics g) {
    g.setColor(Color.GREEN);
    g.fillOval(x - r, y- r, r*2, r*2);
}

public void update() {
    if(enlarge) {
        makeLarger = new MakeLarger();
        makeLarger.start();
    } else {
        makeSmaller = new MakeSmaller();
        makeSmaller.start();
    }
}


private class MakeLarger extends Thread {

    public void run()  {
        while(true) {
            x = getWidth()/2;
            y = getHeight()/2;

            if(getWidth() > getHeight()) {
                if(r < getHeight()/2) {
                    r++;
                    repaint();
                    try {
                    sleep(25);
                    } catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    enlarge = false;
                    update();
                    Thread.currentThread().interrupt();
                    return;
                }
            } else {
                if(r < getWidth()/2) {
                    r++;
                    repaint();
                    try {
                        sleep(25);
                        } catch(InterruptedException e) {
                            e.printStackTrace();
                        }
                }   else {
                    enlarge = false;
                    update();
                    Thread.currentThread().interrupt();
                    return;
                }
            }
        }
    }

}
private class MakeSmaller extends Thread {

    public void run()  {
        while(true) {
            x = getWidth()/2;
            y = getHeight()/2;

                if(r > 50) {
                    r--;
                    repaint();
                    revalidate();
                    try {
                    sleep(25);
                    } catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    enlarge = true;
                    update();
                    Thread.currentThread().interrupt();
                    return;
                }
            }

      }

  }
}

当我启动我的小程序时,椭圆开始正常生长,直到它撞到边界然后突然停止。

我认为第一件事是它没有正确变小。但是一个小的System.out.println工作向我展示了所有计算都正确进行,问题是applet仅在makeLarger线程处于活动状态时重新绘制,当makeSmaller线程处于工作状态时,对repaint()的调用没有&#39工作! 如果我在makeSmaller Thread工作时重新调整applet窗口的大小,它会正确重新绘制,显示椭圆变小。

有人可以在这个奇怪的行为上让我高兴吗? 我错过了什么?

感谢大家最感谢您的帮助,如果我的英语太差了,请抱歉!

2 个答案:

答案 0 :(得分:4)

我不能说我已经查看了所有代码,但提出了一些建议:

  • 在JPanel的paintComponent覆盖中绘制。
  • 这是关键:在覆盖的第一行调用super.paintComponent方法。这消除了先前的图像,使图像变小。
  • 通过将JAPlet中的JPanel添加到小程序中来显示它。
  • 我自己,我使用单个Swing Timer作为动画循环,并使用布尔值来决定大小调整的方向。
  • 但无论我是使用Swing Timer还是使用线程中的Runnable,我都会尽量让事情变得简单,这意味着使用一个改变调整大小方向的计时器或者单个Runnable / Thread,根据布尔值更改调整大小的大小。这种你正在进行的线程交换只会过度和不必要地使事情变得复杂,很可能是你错误的根源。
  • 作为附带建议,您几乎不想扩展Thread。更好的是创建实现Runnable的类,然后当你需要在后台线程中运行它们时,创建一个Thread,将Runnable传入Thread的构造函数,然后调用start()线程。

答案 1 :(得分:1)

首先,谢谢大家的帮助!

我试图解决的问题是:

  

制作一个显示绿色椭圆形的小程序,直到它碰到边框,然后它应该开始变小到一个固定的半径(50),然后它应该重新开始(和结束)。通过制作两个线程(通过扩展Thread)来解决问题。

只是解释为什么这个算法太奇怪了!

好吧,阅读你的建议我修复了我的代码,现在它正常运行。如果有人需要,这是代码。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

import javax.swing.JApplet;
import javax.swing.Timer;

public class Disco extends JApplet{

    private int x;
    private int y;
    private int r;
    private boolean enlarge;
    MakeLarger makeLarger;
    MakeSmaller makeSmaller;

    public void init() {}

    public void start() {
        x = getWidth()/2;
        y = getHeight()/2;
        r = 50;
        enlarge = true;
        makeLarger = new MakeLarger();
        makeLarger.start();
        Timer timer = new Timer(1000/60, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                repaint();
            }
        });
        timer.start();
    }

    public void paint(Graphics g) {
        BufferedImage offScreenImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_4BYTE_ABGR_PRE);
        Graphics2D g2D = (Graphics2D) offScreenImage.getGraphics();
        g2D.clearRect(0, 0, getWidth(), getHeight());
        g2D.setColor(Color.GREEN);
        g2D.fillOval(x - r, y- r, r*2, r*2);

        g.drawImage(offScreenImage, 0, 0, this);
    }

    public void update() {
        if(enlarge) {
            makeLarger = new MakeLarger();
            makeLarger.start();
        } else {
            makeSmaller = new MakeSmaller();
            makeSmaller.start();
        }
    }


    private class MakeLarger extends Thread {

        public void run()  {
            while(true) {
                x = getWidth()/2;
                y = getHeight()/2;

                if(getWidth() > getHeight()) {
                    if(r < getHeight()/2) {
                        r++;
                        try {
                        sleep(25);
                        } catch(InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        enlarge = false;
                        update();
                        Thread.currentThread().interrupt();
                        return;
                    }
                } else {
                    if(r < getWidth()/2) {
                        r++;
                        try {
                            sleep(25);
                            } catch(InterruptedException e) {
                                e.printStackTrace();
                            }
                    }   else {
                        enlarge = false;
                        update();
                        Thread.currentThread().interrupt();
                        return;
                    }
                }
            }
        }

    }
    private class MakeSmaller extends Thread {

        public void run()  {
            while(true) {
                x = getWidth()/2;
                y = getHeight()/2;

                    if(r > 50) {
                        r--;
                        try {
                        sleep(25);
                        } catch(InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        enlarge = true;
                        update();
                        Thread.currentThread().interrupt();
                        return;
                    }
                }

        }

      }
    }