Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lab11_Java_Vkazivky_2010_Mutimedia in Java_ Ima....doc
Скачиваний:
1
Добавлен:
17.04.2019
Размер:
863.23 Кб
Скачать

Import java.Awt.*;

Import java.Awt.Event.*;

class SimpleAnim extends Frame{

private Image[] img = new Image[10];

private int count;

SimpleAnim(String s){ super(s);

MediaTracker tr = new MediaTracker(this);

for (int k = 0; k < 10; k++){

img[k] = getToolkit().getImage("run"+ String.valueOf(k) +".gif");

tr.addImage(img[k], 0);

}

try{

tr.waitForAll(); // Чекаємо завантаження всіх зображень

}

catch(InterruptedException e){}

setSize(400, 300);

setVisible(true);

}

public void paint(Graphics g){

g.drawImage(img[count % 10], 0, 0, this);

}

// public void update(Graphics g){ paint(g); }

public void go(){ while(count < 100){

repaint(); // Виводимо наступний кадр

try{ // Затримка в 0.1 сек

Thread.sleep(100);

}catch(InterruptedException e){count++;}

}

}

public static void main(String[] args){

SimpleAnim f = new SimpleAnim(" Проста анімація");

f.go();

f.addWindowListener(new WindowAdapter(){

public void windowClosing(WindowEvent ev){

System.exit(0); }

});

}

}

Якщо кадри анімації повністю перерисовують вікно, то його очистка методом clearRect() не потрібна. Більше того, вона часто викликає неприємне мерехтіння із-за появи на мить білого фону. В такому випадку треба зробити наступне перевизначення:

public void update(Graphics g) {

paint(g);

}

В лістинзі 15.9 це перевизначення зроблено як коментар.

Для "легких" компонентів справа складніша. Метод repaint() послідовно звертається до методів repaint() обмежуючих "легких" контейнерів, поки не зустрінеться "важкий" контейнер, частіше всього це екземпляр класу Container. В ньому викликається метод update(), очищаючий і перерисовуючий контейнер. Після цього йде звернення до методів update() обмежуючих всі "легкі" компоненти в контейнері. Звідси слідує, що для усунення мерехтіння "легких" компонентів необхідно перевизначити метод update() першого обмежуючого "важкого" контейнера, звертаючись в ньому до методів super.update (g) або super.paint(g). Якщо кадри покривають тільки частину вікна, причому кожний раз нову, то очистка вікна необхідна, інакше старі кадри залишаться у вікні, зявится "хвіст". Щоб усунути мерехтіння, використовують прийом, одержавший назвуе "подвійна буферизація " (double buffering).

15.13. Покращення зображення подвійною буферизацією

Суть подвійної буферизації в тому, що в оперативній памяті створюється буфер — обєкт класу Image або BufferedІmage, і викликається його графічний контекст, в якому формується зображення. Там же відбувається очистка буфера, яка теж не відображається на екрані. Тільки після виконання всіх дій готове зображення виводиться на екран. Все це відбувається в методі update(), а метод paint() тільки звертається до update(). Лістинги 15.10—15.11 пояснюють даний прийом.

Лістинг 15.10. Подвійна буферизація за допомогою класу image

public void update(Graphics g){

int w = getSize().width, h = getSize().height;

// Створюємо зображення-буфер в оперативній памяті

Image offImg = createImage(w, h);

// Одержуємо його графічний контекст

Graphics offGr = offImg.getGraphics();

// Змінюємо поточний колір буфера на колір фону

offGr.setColor(getBackground());

//и заповнюємо ним вікно компонента, очищуючи буфер

offGr.fillRect(0, 0, w, h);

// Повертаємо поточний колір буфера

offGr.setColor(getForeground());

// Для лістингу 15.9 виводимо в контекст зображення

offGr.drawImage(img[count % 10], 0, 0, this);

// Рисуємо в графічному контексті буфера

// (необовязкова дія)

paint(offGr);

// Виводимо зображення-буфер на экран

// (можно перенести в метод paint())

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

// Метод paint() необовязковий

public void paint(Graphics g).update(g); }

Лістинг 15.11. Подвійна буферизація за допомогою класу BufferedІmage

public void update(Graphics g){

Graphics2D g2 = (Graphics2D},g;

int w = getSize().width, h = getSize().height;

// Створюємо зображення-буфер в оперативній памяті

BufferedImage bi = (BufferedImage)createImage(w, h);

// Створюємо графічний контекст буфера

Graphics2D big = bi.createGraphics();

// Установлюємо колір фону

big.setColor(getBackground());

// Очищаємо буфер кольором фону

big.clearRect(0, 0, w, h);

// Відновлюємо поточний колір

big.setColor(getForeground());

// Виводимо що-небудь в графічний контекст big

// ...

// Виводимо буфер на экран

g2.drawImage(bi, 0, 0, this);

}

Метод подвійної буферизації став фактичнo стандартом виведення змінних зображень, а в бібліотеці Swing він застосовується автоматично. Даний метод зручний і при перерисовуванні окремих частин зображення. В цьому випадку в зображенні-буфері рисується незмінна частина зображення, а в методі paint() — те, що змінюється при кожному перерисовуванні.

В лістинзі 15.12 показано другий спосіб анімації — кадри зображення рисуютсья безпосередньо в програмі, в методі update(), по заданому закону зміни зображення. В результаті червоний мячик плигає на фоні зображення.

Лiстинг 15.12. Анімація рисуванням

import java.awt.*;

import java.awt.event.*;

import java.awt.geom.*;

import java.awt.image.*;

class DrawAnim extends Frame{

private Image img;

private int count;

DrawAnim(String s) {

super(s);

MediaTracker tr = new MediaTracker(this);

img = getToolkit().getImage("IMG_0106.jpg");

tr.addImage(img, 0);

try{

tr.waitForID(0) ;

}catch(InterruptedException e) {}

setSize(1200, 800);

setVisible(true);

}

public void update(Graphics g){

Graphics2D g2 = (Graphics2D)g;

int w = getSize().width, h = getSize().height;

BufferedImage bi = (BufferedImage)createImage(w, h) ;

Graphics2D big = bi.createGraphics();

// Заповнюємо фон зображенням img

big.drawImage(img, 0, 0, this);

// Установлюємо колір рисования

big.setColor(Color.red);

// Рисуємо в графічному контексті буфера круг,

// перемещающийся по синусоиде

big.fill(new Arc2D.Double(4*count, 50+30*Math.sin(count),

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]