Мне нужна помощь, чтобы понять, как написать код для двойной буферизации в Java-апплетах

Я понимаю логику этого, но не знаю, как перевести это в код. Может кто-нибудь показать мне пример, который я написал?

Все, что делает апплет, это то, что центральный прямоугольник перемещается вверх, вниз, вправо и влево самостоятельно. Я хочу избавиться от надоедливого мерцания с помощью двойного буфера, но я не знаю, какие изменения / добавления нужно сделать, чтобы это произошло.

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

2 ответа

Решение
  1. import java.awt.*;
    Изменить это на
    import javax.swing.*;
  2. public class Broadway extends Applet ..
    Изменить это на
    public class Broadway extends JApplet ..
  3. Переместить все пользовательские картины в JPanel, Override paintComponent(Graphics) скорее, чем paint(Graphics), JPanelпо умолчанию с двойной буферизацией.
  4. Делайте анимацию, используя Swing Timer,

Как общий совет

Кодируйте фрейм и запускайте его по ссылке, используя Java Web Start, прежде чем рассматривать возможность использования апплета.

Обновить

Этот код реализует большую часть приведенных выше советов и отображает полученную плавную буферизованную анимацию на панели параметров. Вместо этого он может отображаться в JFrame или же 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);
    }
}

По сути, вы заменяете метод рисования так, чтобы он рисовал изображение того же размера, что и апплет, а затем рисуете это изображение на Graphics g,

Там много реализаций там.

Смежные вопросы:

Другие вопросы по тегам