Question

I understand the logic behind it, but don't know how to translate that to code. Could someone please show me on this example that I wrote?

All the applet does is that the center rectangle moves up, down, right and left of its own accord. I want to get rid of the annoying flicker with a double buffer, but I don't know what change/add to make that happen.

import java.applet.*;

import java.awt.*;

public class Broadway extends Applet implements Runnable {

Thread animation;

int locx,locy; // location of rectangle
int width, height; // dimensions of rectangle

// direction of motion
static final byte UP = 0; 
static final byte DOWN = 1;
static final byte LEFT = 2;
static final byte RIGHT = 3;

byte state; // state the rect is in

// length of pausing interval in ms
static final int REFRESH_RATE = 100;


public void init() {

    setBackground(Color.black);

    locx = 80; // parameters of center rect
    locy = 100;
    width = 110;
    height = 90;
    state = UP;
}

public void start() {

    animation = new Thread(this);

    if (animation != null) {
    animation.start();
    }
}

public void paint(Graphics g) {

    g.setColor(Color.yellow);
    g.fillRect(0,0,90,90);
    g.fillRect(250,0,40,190);
    g.fillRect(80,110,100,20);

    g.setColor(Color.blue);
    g.fillRect(80,200,220,90);
    g.fillRect(100,10,90,80);

    g.setColor(Color.lightGray);
    g.fillRect(locx,locy,width,height);

    g.setColor(Color.red);
    g.fillRect(200,0,45,45);
    g.fillRect(0,100,70,200);

    g.setColor(Color.magenta);
    g.fillRect(200,55,60,135);
}

//update the center rectangle
void updateRectangle() {

    switch (state) {
    case DOWN:
        locy += 2;
        if (locy >= 110) {
        state = UP;
        }
        break;
    case UP:
        locy -= 2;
        if (locy <= 90) {
        state = RIGHT;
        }
        break;
    case RIGHT:
        locx += 2;
        if (locx >= 90) {
        state = LEFT;
        }
        break;
    case LEFT:
        locx -= 2;
        if (locx <= 70) {
        state = DOWN;
        }
        break;
    }
}

public void run() {

    while (true) {
        repaint();  
        updateRectangle();              
        try {
        Thread.sleep (REFRESH_RATE);    
        } catch (Exception exc) { };
    }
}

public void stop() {

    if (animation != null) {
    animation.stop();
    animation = null;
    }
}
}
Was it helpful?

Solution

  1. import java.awt.*;
    Change that to
    import javax.swing.*;
  2. public class Broadway extends Applet ..
    Change that to
    public class Broadway extends JApplet ..
  3. Move all the custom painting into a JPanel. Override paintComponent(Graphics) rather than paint(Graphics). A JPanel is double buffered by default.
  4. Do animation using a Swing Timer.

As a general tip

Code a frame & launch it from a link using Java Web Start before considering using an applet.

Update

This code implements most of the advice above, and displays the resulting smooth, buffered animation in an option pane. It could instead be displayed in a JFrame or JApplet.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class Broadway extends JPanel {

    int locx, locy; // location of rectangle
    int width, height; // dimensions of rectangle
    Timer timer;
// direction of motion
    static final byte UP = 0;
    static final byte DOWN = 1;
    static final byte LEFT = 2;
    static final byte RIGHT = 3;
    byte state; // state the rect is in
// length of pausing interval in ms
    static final int REFRESH_RATE = 100;

    public Broadway() {

        setBackground(Color.black);

        locx = 80; // parameters of center rect
        locy = 100;
        width = 110;
        height = 90;
        state = UP;

        ActionListener listener = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                repaint();
                updateRectangle();
            }
        };

        timer = new Timer(this.REFRESH_RATE, listener);
    }

    public void start() {
        timer.start();
    }

    public void stop() {
        timer.stop();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.yellow);
        g.fillRect(0, 0, 90, 90);
        g.fillRect(250, 0, 40, 190);
        g.fillRect(80, 110, 100, 20);

        g.setColor(Color.blue);
        g.fillRect(80, 200, 220, 90);
        g.fillRect(100, 10, 90, 80);

        g.setColor(Color.lightGray);
        g.fillRect(locx, locy, width, height);

        g.setColor(Color.red);
        g.fillRect(200, 0, 45, 45);
        g.fillRect(0, 100, 70, 200);

        g.setColor(Color.magenta);
        g.fillRect(200, 55, 60, 135);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(300, 300);
    }

//update the center rectangle
    void updateRectangle() {

        switch (state) {
            case DOWN:
                locy += 2;
                if (locy >= 110) {
                    state = UP;
                }
                break;
            case UP:
                locy -= 2;
                if (locy <= 90) {
                    state = RIGHT;
                }
                break;
            case RIGHT:
                locx += 2;
                if (locx >= 90) {
                    state = LEFT;
                }
                break;
            case LEFT:
                locx -= 2;
                if (locx <= 70) {
                    state = DOWN;
                }
                break;
        }
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                Broadway bw  = new Broadway();

                bw.start();
                JOptionPane.showMessageDialog(null, bw);
                bw.stop();
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
        SwingUtilities.invokeLater(r);
    }
}

OTHER TIPS

Basically you replace the paint method so that it paints to an Image the same size as the Applet, then draw that image on Graphics g.

There's plenty of implementations out there.

Related questions:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top