简体   繁体   中英

Repaint() working only half times

i've got a problem with what should be a simple excercise. I've been asked to make an applet that prints a green oval (filled) that becomes larger until it hits the borders, than start becoming smaller. This should go on until you close the applet.

Well, i came out with this code

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

      }

  }
}

When I start my applet the oval start growing correctly until it hits the border and then suddently stop.

The first thing i thought was that it wasn't getting smaller correctly. But a little System.out.println work showed me that all computation was going on correctly, the problem is that the applet repaint only while the makeLarger thread is active, when the makeSmaller thread is at work the call to repaint() doesn't work! If i resize the applet window while the makeSmaller Thread is at work it repaints correctly showing me the oval getting smaller.

Can, please, someone enlight me on this odd behavior? What am I missing?

thank you everyone for your most appreciated help and sorry if my english is so poor!

I can't say that I've looked at all the code, but a couple of suggestions:

  • Paint in a JPanel's paintComponent override.
  • This is key: call the super.paintComponent method in the override, first line. This gets rid of prior images so that the image can get smaller.
  • Display the JPanel within your JApplet by adding it to the applet.
  • Myself, I'd use a single Swing Timer for the animation loop, and would use a boolean to decide which direction the sizing should go.
  • But regardless of whether I were using a Swing Timer or a Runnable placed in a Thread, I'd try to keep things a simple as possible, and that would mean using a single Timer that changes direction of resizing or a single Runnable/Thread that changes size of resizing based on a boolean. This swapping of threads that you're doing just serves to overly and unnecessarily complicate things, and could quite possibly be the source of your error.
  • As a side recommendation, you almost never want to extend Thread. Much better is to create classes that implement Runnable, and then when you need to run them in a background thread, create a Thread, passing in your Runnable into the Thread's constructor, and then calling start() on the Thread.

First things first, thank you all for helping me!

The problem I was trying to solve was this:

Make an applet which shows a green oval getting larger until it hits the borders, then it should start getting smaller up to a fixed radius (50), then it should start over (and over) again. Solve the problem by making two threads (by extending Thread).

Just to explain why the algorithm was so odd!

Well, reading your suggestions I fixed my code, now it's running properly. Here is the code if anyone will need this.

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

        }

      }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM