background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 1 

8. Multimedia. Klasa 

Graphics

 

 
 
 

8.1 Operowanie na obrazach 
8.2 Animacje 
8.3 D

ź

wi

ę

ki 

8.4 

Graphics

 

 

 
 
 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 2 

8.1 Operowanie na obrazach 

Operacje na obrazach wspomagaj

ą

 pakiety:  

java.applet, java.awt, java.awt.image. 

 
Obraz reprezentowany jest jako obiekt klasy 

java.awt.Image

 


 Podstawowa  metoda  dla  obrazu  w  klasie 

java.awt.Graphics

  to 

drawImage

,  w  klasie 

java.awt.Toolkit

  -  metoda 

getImage

  a  tak

Ŝ

metody klasy 

java.awt.MediaTracker

 



 W  pakiecie 

java.applet

  metoda  klasy 

Applet  - 

getImage

  –  umo

Ŝ

liwia 

pobieranie obrazów z plików graficznych. 

 



 Pakiet 

java.awt.image

 zapewnia interfejsy i klasy dla tworzenia, (np.. 

MemoryImageSource

), 

przetwarzania 

(np. 

ConvolveOp, 

RGBImageFilter

) i nadzorowania ładowania (np. 

ImageObserver

). 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 3 

1) Ładowanie obrazów 

Metody 

getImage()

 

Obrazy  w  formatach 

GIF

JPEG

  lub 

PNG

  ładowane  mog

ą

  by

ć

 

metodami 

getImage

() 

deklarowanymi w klasach 

Applet

 i 

Toolkit

. Np. 

myImage = getImage(URL);

 

// w klasach pochodnych od Applet

 

    // LUB w klasach pochodnych od Toolkit: 

myImage = Toolkit.getDefaultToolkit().getImage(nazwaPlikuLubURL); 

 
Metody 

getImage()

 

powracaj

ą

  natychmiast

,  nie  oczekuj

ą

c  na 

potwierdzenie  istnienia  obrazu  ani  na  jego  załadowanie.  Ładowanie 
odb

ę

dzie  si

ę

  wtedy,  gdy  obraz  po  raz  pierwszy  b

ę

dzie  malowany  w 

programie. 
 
W klasie 

Toolkit

 istniej

ą

 dwie deklaracje metod o tej nazwie: 

public abstract 

Image getImage(URL url); 

public abstract

 Image getImage(String filename); 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 4 

Metody  te  mog

ą

  by

ć

  wołane  w  aplikacjach  lub  apletach  (ale  w  tym 

drugim przypadku aplety musz

ą

 spełnia

ć

 warunki dost

ę

pu). 

Np.  

Toolkit toolkit = Toolkit.getDefaultToolkit(); 
Image image1 = toolkit.getImage("nazwaObrazu.gif"); 

Image image2 = toolkit.getImage(new URL("http://www.pw.edu.pl/pw.gif")); 

 

W klasie 

Applet

 istniej

ą

 dwie wersje tej metody: 

public 

Image getImage(URL url);  

public

 Image getImage(URL url, String name);  

Mog

ą

  by

ć

  wołane  tylko  w  apletach  i  dopiero  po  uzyskaniu  pełnego 

kontekstu  przez  aplet  –  nie  w  konstruktorze  ani  w  instrukcji  deklaracji 
obiektu. 
Np. 

// W metodzie pewnej klasy pochodnej od Applet: 

Image image1 = getImage(getCodeBase(), "pw.gif"); 
Image image2 = getImage(getDocumentBase(), "pw.jpeg"); 
Image image3 = getImage( new URL("http://www.pw.edu.pl/pw.gif")); 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 5 

2) Tworzenie obrazów za pomoc

ą

 klasy 

MemoryImageSource 

Nowe  obrazy  mog

ą

  by

ć

  tworzone  od  pocz

ą

tku  dzi

ę

ki  klasie 

java.awt.image.

MemoryImageSource

.

 

 

Przykład 8.1. 

Fragment programu przeznaczony dla utworzenia obrazu 

o  rozmiarze  100  x  100,  przedstawiaj

ą

cego  odcienie  od  czarnego  do 

niebieskiego  (wzdłu

Ŝ

  osi  X)  i  odcienie  od  czarnego  do  czerwonego 

(wzdłu

Ŝ

 osi Y): 

int w = 100; 
int h = 100; 
int[] pix = new int[w * h]; 
int index = 0; 
for (int y = 0; y < h; y++) { 
    int red = (y * 255) / (h - 1); 
    for (int x = 0; x < w; x++) { 
          int blue = (x * 255) / (w - 1); 
          pix[index++] = (255 << 24) | (red << 16) | blue; 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 6 

    } 

Image img = createImage(new MemoryImageSource(w, h, pix, 0, w)); 

 

3) Nadzorowanie ładowania obrazów 

Proces  ładowania  obrazu  mo

Ŝ

e  by

ć

  nadzorowany  przez  klas

ę

 

java.awt.

MediaTracker

 lub przez implementacj

ę

 metody 

imageUpdate()

 

(zdefiniowanej w interfejsie 

java.awt.image.

ImageObserver

). 

 
Interfejs 

ImageObserver

 

 

Wymaga implementacji metody 

imageUpdate()

 i rejestracji obiektu jako 

„obserwatora”  –  zwykle  ma  to  miejsce  poprzez  przekazanie  obiektu 
typu implementuj

ą

cego 

ImageObserver

 do metody 

drawImage

(). 

public boolean imageUpdate(Image img,  

int infoflags,  int x, int y, int width, int height); 

Metoda  powinna  zwróci

ć

  false  wtedy,  gdy  przakzane  argumenty 

wskazuj

ą

Ŝ

e cały obraz został juz załadowany.  

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 7 

4) Rysowanie obrazu 

Metoda 

drawImage()

 wołana dla obiektu klasy 

Graphics

 przekazanego 

do metody 

paintComponent().

 Np.: 

// Normalny rozmiar obrazu. Lokalizacja pocz

ą

tku w górnym lewym  

// rogu obszaru komponentu. 

g.drawImage(myImage, 0, 0, this);  

// Obraz przeskalowany do rozmiaru: 300 x 62 piksele i lokalizacji 
// pocz

ą

tku w punkcie (90, 0) obszaru komponentu:  

g.drawImage(myImage, 90, 0, 300, 62, this); 

 
Metoda 

drawImage

  tak

Ŝ

e  (jak 

getImage()

)  działa  asynchronicznie 

wzgl

ę

dem  ładowania  obrazu  -  powraca  po  narysowaniu  fragmentu 

obrazu, który został dot

ą

d załadowany. 

 
Cztery  metody 

drawImage

  w  klasie 

Graphics

  (zwracaj

ą

  wynik  typu 

boolean

”): 

boolean drawImage (Image img, int x, int y, ImageObserver observer)  
boolean drawImage (Image img, int x, int y, int width, int height,  

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 8 

ImageObserver observer)  

boolean drawImage (Image img, int x, int y, Color bgcolor,  

ImageObserver observer)  

boolean drawImage (Image img, int x, int y, int width, int height,  

Color bgcolor, ImageObserver observer)  

Znaczenie parametrów metod 

drawImage()



 

Image img – rysowany obraz; 



 

int x, int y  – współrzędne górnego lewego rogu obrazu ;  



 

int width, int height – szerokość i wysokość obrazu (w pikselach); 



 

Color bgcolor – kolor tła. 



 

ImageObserver  observer  –  rejestracja  obiektu  implementującego 
interfejs ImageObserver – ten obiekt będzie powiadamiany o ładowaniu 
obrazu. 

Klasa 

Component

  implementuje  interfejs 

ImageObserver

,  czyli  ka

Ŝ

dy 

komponent  GUI  mo

Ŝ

e  przekaza

ć

  siebie  (poprzez 

this

)  jako 

obserwatora.  Ta  implementacja  metody 

imageUpdate

  interfejsu 

wywołuje metod

ę

 

repaint

, gdy obraz jest ładowany. 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 9 

8.2 Wykonanie animacji 

1) P

ę

tla animacji z wykorzystaniem klasy 

Timer

  

P

ę

tla  animacji  powinna  wykonywa

ć

  si

ę

  w  osobnym  w

ą

tku,  a  nie  w 

metodzie 

paintComponent()

,  gdy

Ŝ

  to  umie

ś

ciłoby  animacj

ę

  w  w

ą

tku 

obsługi zdarze

ń

 (“event-dispatching”). 

Przykład  8.2

.  Prosta  animacja  podaj

ą

ca  kolejny  numer  ramki  z 

cz

ę

sto

ś

ci

ą

 10 ramek na sekund

ę

:      

 

public class AnimatorClass ... implements ActionListener { 
    int frameNumber = -1; 
    Timer timer; 
    boolean frozen = false; 

// Nie blokujemy animacji 

    JLabel label; 

// Komponent realizujący rysowanie

 

   // W kodzie inicjalizacji GUI:  
   // Na podstawie liczby ramek na sekundę fps określamy odstęp czasu - delay 

        delay = (fps > 0) ? (1000 / fps) : 100; 

       ... 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 10 

        // Obiekt klasy Timer będzie wołał obsługę akcji w naszym obiekcie. 

        

timer = new Timer(delay, this);

 

// Obiekt klasy Timer generować będzie  

       // zdarzenie akcji co pewną liczbę „delay” milisekund

  

 // i dalsze ustawienie komponentów w GUI. 

... 

 // Gdy pojawi się GUI aplikacji: 

        startAnimation(); 

// Gdy GUI jest ukrywane: 

        stopAnimation(); 
… 

//Obsługa zdarzenia akcji dla timer-a:  

    public void actionPerformed(ActionEvent e) { 
        frameNumber++;  

        // Zwiększ numer ramki  

        label.setText("Frame " + frameNumber);

 // Zmiana tekstu i narysowanie 

    } 

// Metody uruchamiania i zatrzymywania animacji: 

public synchronized void startAnimation() { 
    if (frozen) { 

 // Nie wykonuj animacji

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 11 

    } else { 

  

// Rozpocznij animację ! 

        ... 
        timer.start(); 
    } 
public synchronized void stopAnimation() { 
    ... 
    timer.stop(); 

 

Uruchamianie  i  zatrzymanie  animacji  mo

Ŝ

e  by

ć

  te

Ŝ

  inicjowane  w 

obsłudze zdarze

ń

 myszy dla komponentu realizuj

ą

cego animacj

ę

: 

public void mousePressed(MouseEvent e) { 
    if (frozen) {  frozen = false; 
        startAnimation(); 
    } else {  frozen = true; 
        stopAnimation(); 
    } 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 12 

2) Przesuwanie obrazu po ekranie 

Przykład 8.3.

 Program realizuje animacj

ę

, podczas której obraz rakiety 

przesuwa si

ę

 na tle obrazu gwiazd: 

rocketship.gif:   

 

 

starfield.gif: 

 

 
Jedna klatka animacji: 

 

Obraz rakiety posiada przezroczyste tło. 

W panelu definiowanym przez programist

ę

 malowane s

ą

 dwa obrazy, z 

których  pozycja  jednego  nie  zale

Ŝ

y  a  drugiego  zale

Ŝ

y  od  numeru 

aktualnej ramki. 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 13 

...// Miejsce inicjalizacji obrazów: 

Image background = getImage(getCodeBase(), "images/rocketship.gif"); 
Image foreground = getImage(getCodeBase(), "images/starfield.gif"); 
... 
public void paintComponent(Graphics g) { 
    super.paintComponent(g);

 

// Rysuje obszar komponentu 

    int compWidth = getWidth(); 
    int compHeight = getHeight();

 

    // Namaluj obraz w tle, je

ś

li posiada wła

ś

ciwy rozmiar: 

    imageWidth = background.getWidth(this); 
    imageHeight = background.getHeight(this); 
    if ((imageWidth > 0) && (imageHeight > 0)) { 
        g.drawImage(background, (compWidth - imageWidth)/2, 
                                        (compHeight - imageHeight)/2, this); 
    } 

    // Namaluj obraz na 1-szym planie, je

ś

li posiada wła

ś

ciwy rozmiar: 

    imageWidth = foreground.getWidth(this); 
    imageHeight = foreground.getHeight(this); 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 14 

    if ((imageWidth > 0) && (imageHeight > 0)) { 
        g.drawImage(foreground,  
              ((frameNumber*5)  %  (imageWidth + compWidth))  - imageWidth, 
                    (compHeight - imageHeight)/2,  this); 
    } 

 
Program  wymaga  jeszcze  synchronizacji  rysowania  z  załadowaniem 
obu  obrazów  –  odczekania  na  pełne  załadowanie  obu  obrazów  –  i 
przeskalowania obrazu tła tak, aby wypełniał cały obszar panelu.  
Do tego celu posłu

Ŝ

y klasa 

MediaTracker

, omówiona w punkcie 4. 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 15 

3) Wy

ś

wietlanie sekwencji obrazów 

Przykład 8.4.

 Aplet wy

ś

wietla sekwencj

ę

 10 obrazów: 

T1.gif: 

T2.gif: 

T3.gif: 

T4.gif: 

T5.gif: 

 

T6.gif: 

T7.gif: 

T8.gif: 

T9.gif: 

T10.gif: 

 

. . .//  W kodzie inicjalizacji: 

Image[] images = new Image[10]; 
for (int i = 1; i <= 10; i++) { 
    images[i-1] = getImage(getCodeBase(), "images/duke/T"+i+".gif"); 

. . .// W metodzie 

paintComponent

 - w zale

Ŝ

no

ś

ci od numeru ramki: 

g.drawImage(images[frameNumber % 10],  0, 0, this); 

 
Alternatywna  metoda  animacji  to  wykorzystanie  komponentu  etykiety 

JLabel

 i ustawianie wy

ś

wietlanego obrazu metod

ą

 

setIcon

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 16 

4) Animacja z wykorzystaniem 

MediaTracker

  

 

Klasa 

MediaTracker

  umo

Ŝ

liwi  efektywne  ładowanie  obrazów  i  opó

ź

ni 

ich wy

ś

wietlenie do momentu, gdy b

ę

d

ą

 one dost

ę

pne w cało

ś

ci. 

Klasa 

MediaTracker

 posiada metody dla wcze

ś

niejszego ni

Ŝ

 potrzebne 

(tzn. podczas rysowania komponentu) załadowania obrazów. 
 
Poni

Ŝ

sze metody sprawdzaj

ą

, czy pozostały jeszcze fragmenty obrazu 

(lub obrazy) wymagaj

ą

ce załadowania. 

public  boolean  checkAll() 







  checkAll(false,  true) 

//  sprawdza,  czy 

wszystkie  obrazy  nadzorowane  przez  ten  obiekt  zostały  załadowane  (lub 
wystąpił błąd ładowania) 

public  boolean  checkAll(boolean  load







  checkAll(load,  true)

 

// 

sprawdza,  czy  wszystkie  obrazy  nadzorowane  przez  ten  obiekt  zostały 
załadowane  (lub  wystąpił  błąd  ładowania);  jeśli  load  =  true  to  inicjuje 
ładowanie  wszystkich  przewidzianych  ale  jeszcze  nieładowanych 
obrazów. 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 17 

public  boolean  checkID(int  id

//  sprawdza,  czy  obrazy  o  podanym 

identyfikatorze,  nadzorowane  przez  ten  obiekt,  zostały  załadowane  (lub 
wystąpił błąd ładowania) 

public boolean checkID(int id, boolean load

// sprawdza, czy obrazy o 

podanym  obrazy  o  podanym  identyfikatorze,  nadzorowane  przez  ten 
obiekt, zostały załadowane (lub wystąpił błąd ładowania); jeśli load = true 
to inicjuje ładowanie wszystkich jeszcze nieładowanych obrazów. 

Poni

Ŝ

sze  metody inicjuj

ą

 ładowanie  i oczekuj

ą

 na załadowanie  całych 

obrazów: 

public void waitForID (int id

// inicjuje ładowanie obrazów o podanym 

identyfikatorze i czeka na zakończenie ładowania 

public void waitForID (int id, long ms

// inicjuje ładowanie obrazów o 

podanym identyfikatorze i czeka na zakończenie ładowania, ale nie dłuŜej 
niŜ liczbę ms milisekund 

public  void  waitForAll() 

//  inicjuje  ładowanie  obrazów  nadzorowanych 

przez ten obiekt i czeka na zakończenie ładowania 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 18 

public  void  waitForAll(long  ms

//  inicjuje  ładowanie  obrazów 

nadzorowanych przez ten obiekt i czeka na zakończenie ładowania, ale nie 
dłuŜej niŜ liczbę ms milisekund 

Sprawdzenie stanu ładowania obrazów. 

public  int  statusID(int  id,  boolean  load

//  sprawdza  stan  ładowania 

obrazów o podanym identyfikatorze id, nadzorowanych przez dany obiekt, 
w  postaci  bitowej  jao  wynik  operacji  OR  na  stanie  wszystkich  tych 
obrazów  –  moŜliwe  stany  to:  0  –  ładowanie  jeszcze  nie  rozpoczęte, 
LOADING,  ABORTED,  ERRORED,  COMPLETE; 

jeśli  load  =  true  to 

inicjuje ładowanie wszystkich jeszcze nieładowanych obrazów. 

public int statusAll(boolean load

// sprawdza stan ładowania wszystkich 

obrazów, nadzorowanych przez dany obiekt. 

Metody klasy 

MediaTracker

 dla dodawania nadzorowanych obrazów: 

public  void  addImage(Image  image,  int  id) 

//  dodaj  obraz  z  podanym 

identyfikatorem 

public  synchronized  void  addImage(Image  image,  int  id,  int  w,  int  h) 

// 

dodaj  obraz  z  podanym  identyfikatorem;  obraz  ma  być  skalowany  na 
podany rozmiar 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 19 

Przykład  8.5

.  Modyfikacja  poprzedniego  apletu  (z  przykładu  8.4) 

korzysta  z  metod 

MediaTracker

 

-  waitForAll

  i 

checkAll

.  Do  momentu 

pełnego  załadowania  wszystkich  obrazów    wy

ś

wietla  komunikat: 

"Please wait..."  

 

Fragmenty  kodu  z  wyró

Ŝ

nionymi  zmianami  w  porównaniu  z 

poprzednim przykładem: 
...// W miejscu deklaracji obiektów : 

MediaTracker tracker; 
tracker = new MediaTracker(this); 

...// W metodzie init: 

for (int i = 1; i <= 10; i++) { 
    images[i-1] = getImage(getCodeBase(), "images/duke/T"+i+".gif"); 

...// W metodzie buildUI, wołanej przez init (dla apletu) wzgl. main  
   // (dla aplikacji) 

for (int i = 1; i <= 10; i++) { 
    tracker.addImage(images[i-1], 0); 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 20 

...// Na pocz

ą

tku obsługi w metodzie actionPerformed : 

try { 

    // Rozpocznij ładowanie obrazów. Czekaj na ich załadowanie. 

    tracker.waitForAll();  
} catch (InterruptedException e) {} 

...// W metodzie paintComponent: 

// Jeśli nie załadowano wszystkich obrazów to wyczyść tło i wyświetl 
// napis ze stanem ładowania: 

if (!tracker.checkAll()) { 
    g.clearRect(0, 0, d.width, d.height); 
    g.drawString("Please wait...", 0, d.height/2); 

// ale jeśli wszystkie obrazy zostały załadowane – namaluj je: 

else { 
    

...// ten sam kod co uprzednio ... 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 21 

5) Efektywno

ść

 ładowania obrazu  

Ładowanie pojedynczych obrazów poprzez adresy URL (jak to zwykle 
czyni

ą

  aplety)  zajmuje  du

Ŝ

o  czasu,  głównie  z  potrzeby  inicjalizacji 

poł

ą

czenia HTTP.  

Sytuacj

ę

  mo

Ŝ

e  poprawi

ć

  umieszczenie  szeregu  obrazów  w 

pojedynczym pliku (np. pliku typu JAR). Np. pasek 4 obrazów jack.gif:  

 

Przykład programu wykre

ś

lania paska obrazów.Niech: 

//

imageStrip

 – to obiekt klasy 

Image

 reprezentuj

ą

cy pasek obrazów. 

//

imageWidth

 – szeroko

ść

 pojedynczego obrazu w pasku.  

//

imageNumber 

– indeks obrazu w pasku (od 0 do 

numImages

). 

int stripWidth = imageStrip.getWidth(this); 
int stripHeight = imageStrip.getHeight(this); 
int imageWidth = stripWidth / numImages; 
g.clipRect(0, 0, imageWidth, stripHeight); 
g.drawImage(imageStrip, -imageNumber*imageWidth, 0, this); 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 22 

8.3 D

ź

wi

ę

ki 

Java Sound Engine

 jest bibliotek

ą

, wyst

ę

puj

ą

c

ą

 w maszynie wirtualnej, 

zapewniaj

ą

c

ą

  odtwarzanie  64-kanałowego  d

ź

wi

ę

ku  i  programow

ą

 

syntez

ę

 d

ź

wi

ę

ku według protokołu MDI.  

 
Klipy d

ź

wi

ę

kowe mog

ą

 by

ć

 nast

ę

puj

ą

cych formatów: 

AIFF, AU, WAV , MIDI (typu 0 lub 1) , RMF . 

 
Dane  mog

ą

  by

ć

  długo

ś

ci  8-  lub  16-bitów.  Standardowo  odtwarzanie 

plików audio odbywa si

ę

 z cz

ę

sto

ś

ci

ą

 22 kHz i w trybie 16-bitów stereo, 

ale mo

Ŝ

liwe s

ą

 te

Ŝ

 tryby 8-bitów lub mono.  

 

Java  Sound  API

  umo

Ŝ

liwia  u

Ŝ

ytkownikowi  odczyt,  odtwarzanie  i  zapis 

d

ź

wi

ę

ku.  

Usługi  wy

Ŝ

szego  rz

ę

du  zwi

ą

zane  z  multimediami  (np.  kompresja, 

dekompresja,  synchronizacja  audio  i  wideo,  transport  w  sieci) 
zapewnia tzw. 

Java Media Framework (JMF)

.  

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 23 

1) Odtwarzanie d

ź

wi

ę

ku w aplecie 

Do 

załadowania 

d

ź

wi

ę

ku 

miejsca 

URL

 

słu

Ŝ

metoda 

Applet.getAudioClip 

public AudioClip getAudioClip(URL url)  
public AudioClip getAudioClip(URL url, String name)  

albo statyczna metoda 

public final static AudioClip newAudioClip(URL url) 

Obie  wersje  metody 

getAudioClip

  tworz

ą

  obiekt  klasy  (zale

Ŝ

nej  od 

kontekstu  apletu)  implementuj

ą

cej  interfejs 

AudioClip

  a  metoda 

newAudioClip

  –  klasy 

sun.applet.AppletAudioClip

,  ale  wracaj

ą

 

natychmiast bez wzgl

ę

du na to, czy istnieje podany adres czy te

Ŝ

 nie. 

Klip b

ę

dzie ładowany przy 1-szej próbie „grania” go przez aplet.  

Do natychmiastowego ładowania i „grania” słu

Ŝą

 metody apletu 

play

.  

 
Do  odtwarzania  klipu  słu

Ŝą

  metody  interfejsu 

java.applet.

AudioClip

:

 

play, loop 

i

 

stop

.  

Ładowanie danych ma miejsce przed pierwszym odtworzeniem. 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 24 

 

Przykład  8.6

.  W  aplecie 

SoundApplet

  pokazano  odtwarzanie  klipów 

Ŝ

nych  typów  - 

AU  ,  AIFF  ,  WAV   

i

  MIDI

  –  umieszczonych  pod 

wspólnym adresem.

  

import javax.swing.*; 
import java.applet.*; 
import java.awt.*; 
import java.awt.event.*; 
 
public class SoundApplet extends JApplet 
                         implements ActionListener, ItemListener { 
    AppletSoundList soundList;

 

// Lista obiektów klipów dźwiękowych

 

    String chosenFile; 

// Nazwa aktualnie wybranego pliku dźwiękowego 

    AudioClip onceClip, loopClip; 

// Tu będą referowane 2 obiekty klipów 

... 

// Korzystamy z klasy pomocniczej  
// class AppletSoundList extends java.util.Hashtable,   
// która zarządza listą plików dźwiękowych o podanych nazwach,  

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 25 

// połoŜonych względem wspólnego globalnego URL: 

soundList = new AppletSoundList(this, getCodeBase());  
… 

// W metodzie obsługi zdarzenia przycisków w oknie apletu 

public void actionPerformed(ActionEvent event) { 

// następuje m.in. pobranie klipu dźwiękowego i jego odtwarzanie 

onceClip = soundList.getClip(chosenFile); //  
loopClip = soundList.getClip(chosenFile); 
... 
onceClip.play(); 

// Jednokrotne odtwarzanie

 

... 
loopClip.loop(); 

// Pętla odtwarzania 

... 
loopClip.stop(); 

// Zatrzymaj odtwarzanie w pętli  

.

.. 

}

 

W  metodach 

start

  

stop

  apletu  nast

ę

puje  wznawianie  i  zatrzymanie 

odtwarzania pliku: 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 26 

public void stop() { 
    onceClip.stop();        

// Zatrzymanie  

    if (looping) { 
        loopClip.stop();    

// Zatrzymanie

  

    } 

public void start() { 
    if (looping) { 
        loopClip.loop();    

// Wznawianie 

    } 

Pliki d

ź

wi

ę

kowe ładowane b

ę

d

ą

 w w

ą

tku pobocznym, w metodzie 

run()

 

obiektu  klasy  pomocniczej 

SoundLoader

  zamiast  w  metodzie 

init()

 

apletu.  Dzi

ę

ki  temu  ładowanie  pliku  nie  b

ę

dzie  blokowało  samego 

apletu.  
 

// W pierwszej klasie pomocniczej nast

ę

puje utworzenie obiektu w

ą

tku 

// dla ka

Ŝ

dego, przez u

Ŝ

ytkownika wybranego pliku d

ź

wi

ę

kowego: 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 27 

class AppletSoundList extends java.util.Hashtable {  

...

  

// W metodzie 

startLoading

 wołanej w konstruktorze obiektu klasy 

// pomocniczej  inicjowana jest lista obiektów klipów dźwiękowych 

public void startLoading(String relativeURL) { 
        new AppletSoundLoader(applet, this, baseURL, relativeURL);  

// Załaduje klipy i przekaŜe je do obiektu typu AppletSoundList 

    } 

 

// Definicja drugiej klasy – dla w

ą

tków realizuj

ą

cych ładowanie plików 

import javax.swing.*; 
import java.applet.*; 
import java.net.URL; 
class AppletSoundLoader extends Thread { 
    JApplet applet; 
    AppletSoundList soundList; 
    URL baseURL; 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 28 

    String relativeURL; 
    public AppletSoundLoader(JApplet applet,  

// Obiekt – aplet SoundApplet 

                             AppletSoundList soundList, 

// Obiekt - lista klipów

 

                             URL baseURL,  
                             String relativeURL) { 
        this.applet = applet; 
        this.soundList = soundList; 
        this.baseURL = baseURL; 
        this.relativeURL = relativeURL; 
        setPriority(MIN_PRIORITY); 
        start(); 

// Aktywuj wątek 

    } 
    public void run() {  

// Metoda run() klasy wątku AppletSoundLoader

 

        AudioClip audioClip = applet.getAudioClip(baseURL, relativeURL); 
        soundList.putClip(audioClip, relativeURL); 

// Dołączy plik do listy 

    } 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 29 

2) Odtwarzanie d

ź

wi

ę

ku w aplikacji  (

newAudioClip()

 ) 

Aplikacje  mog

ą

  ładowa

ć

  klipy  audio  z  dowolnego  miejsca 

URL,

  dzi

ę

ki 

metodzie statycznej 

newAudioClip

 w klasie 

java.applet.Applet

:

 

public static final AudioClip newAudioClip(URL r); 

 
Po  utworzeniu  obiektu  klasy  implementuj

ą

cej 

AudioClip

  metod

ą

 

Applet.newAudioClip

, aplikacja korzysta z metod interfejsu 

AudioClip

:  

 

play, loop, stop

;

 w celu kontroli odtwarzania d

ź

wi

ę

ku.  

 

Przykład.

 Aplikacja 

SoundApplication 

– posiada prawie ten sam kod co 

poprzedni aplet. Jedyn

ą

 zasadnicz

ą

 ró

Ŝ

nic

ą

 jest zast

ą

pienie wywołania 

metody 

getAudioClip

  przez 

Applet.newAudioClip

  w  celu  załadowania 

d

ź

wi

ę

ków z 

URL

AudioClip audioClip = Applet.newAudioClip(new URL(adresPliku)); 

 

  

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 30 

8.4 Klasa 

Graphics

 

Gdy  ikony  w  AWT  lub  Swing-u  nie  wystarczaj

ą

  nam  dla  prezentacji 

grafiki mo

Ŝ

emy skorzysta

ć

 z klas 

Graphics2D

 

lub

 

Graphics

 

1) Kształty  

Klasa 

Graphics 

posiada  metody  dla  rysowania  nast

ę

puj

ą

cych 

kształtów: 



 

linia (drawLine)  



 

prostokąt (drawRect, fillRect)  



 

podwyŜszony lub obniŜony prostokąt (draw3DRect, fill3DRect)  



 

prostokąt o zaokraglonych rogach (drawRoundRect, fillRoundRect)  



 

krzywa zamknięta (drawOval, fillOval)  



 

łuki (drawArc,  fillArc)  



 

wielokąt (drawPolygon, drawPolyline, fillPolygon)  

Np. narysowanie prostokąta: 

g.drawRect(x, y, rectWidth - 1, rectHeight - 1);  

Narysowanie wypełnionego obszaru prostokąta: 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 31 

g.fillRect(x, y, rectWidth, rectHeight); 

Uwaga:  w  metodzie  drawRect  podaje  się  o  1  piksel  mniejszą  szerokość  i 
wysokość,  gdyŜ  system  rysuje  linie  pod  podanym  prostokątem  a  nie  w  jego 
ramach. 
 

Przykład  8.7

Program  rysuje  wypełniony 

Ŝ

ółtym  kolorem  prostok

ą

t  w  

miejscu klikni

ę

cia mysz

ą

 przez u

Ŝ

ytkownika. 

 

GUI  zawiera  dwa  komponenty:  górny  komponent  jest  klasy 
u

Ŝ

ytkownika  RectangleArea  –  zawiera  brzeg  o  dwóch  stanach,  tło  i 

Ŝ

ółty  prostok

ą

t;  dolny  komponent  jest  etykiet

ą

  monitoruj

ą

c

ą

  stan 

programu. 

Kod rysowania dla górnego komponentu: 

class RectangleArea extends JPanel { 
    ... 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 32 

    int rectWidth = 50; 
    int rectHeight = 50; 
    ... 
    public RectangleArea(...) { 
        ... 

       // Definiowanie brzegu dla panelu 

        Border raisedBevel = BorderFactory.createRaisedBevelBorder(); 
        Border loweredBevel = BorderFactory.createLoweredBevelBorder(); 
        Border compound = BorderFactory.createCompoundBorder 
                               

 

 

 

 

  (raisedBevel, loweredBevel); 

        setBorder(compound); 
        ... 
    } 
    ... 
    public void paintComponent(Graphics g) { 
        super.paintComponent(g);

  

// Maluj tło 

 // Maluj wypełniony prostokąt w miejscu wybranym przez uŜytkownika. 

        if (point != null) { 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 33 

            g.drawRect(point.x, point.y,  rectWidth - 1, rectHeight - 1); 
            g.setColor(Color.yellow); 
            g.fillRect(point.x + 1, point.y + 1,  rectWidth - 2, rectHeight - 2); 
            controller.updateLabel(point); 
        } 
    } 

 
W metodzie paintComponent wołane są metody drawRect i fillRect w celu 
narysowania prostokąta o obramowaniu 50 x 50 pikseli wypełnionego Ŝółtym 
prostokątem o rozmiarze 48 x 48 pikseli. 
 

Uwaga:  ujemne  dane  dla  szeroko

ś

ci  lub  wysoko

ś

ci,  albo  punkt 

odniesienia  poło

Ŝ

ony  poza  obszarem,  albo  zbyt  du

Ŝ

e  rozmiary 

prostok

ą

ta  s

ą

  dozwolone,  ale  prowadz

ą

  do  narysowania  niepełnego 

prostok

ą

ta lub całkowicie niewidocznego. 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 34 

Przykład 8.8

.

 Program ilustruje wszystkie kształty. 

 

Fragment kodu rysujący podane kształty: 


 

zmienne rectHeight i rectWidth podają rozmiar prostokąta obejmującego dla 
kaŜdego kształtu, 



 

zmienne x i y są róŜne dla kaŜdego kształtu, aby kształty nie pokrywały się; 



 

zmienne bg i fg są typu Color – wyznaczają one kolor tła i pióra. 

Color fg3D = Color.lightGray; 
... 

// Metoda: drawLine(x1, y1, x2, y2)  

g.drawLine(x, y+rectHeight-1, x + rectWidth, y); 
... 

// Metoda: drawRect(x, y, w, h)  

g.drawRect(x, y, rectWidth, rectHeight); 
... 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 35 

// Metoda: draw3DRect(x, y, w, h, raised)  

g.setColor(fg3D); 
g.draw3DRect(x, y, rectWidth, rectHeight, true); 
g.setColor(fg); 
... 

// Metoda: drawRoundRect(x, y, w, h, arcw, arch)  

g.drawRoundRect(x, y, rectWidth, rectHeight, 10, 10); 
... 

// Metoda: drawOval(x, y, w, h)  

g.drawOval(x, y, rectWidth, rectHeight); 
... 

// Metoda: drawArc(x, y, w, h, startAngle, arcAngle)  

g.drawArc(x, y, rectWidth, rectHeight, 90, 135); 
... 

// Metoda: drawPolygon(xPoints, yPoints, numPoints)  
// Rysuje krzywą zamkniętą 

int x1Points[] = {x, x+rectWidth, x, x+rectWidth}; 
int y1Points[] = {y, y+rectHeight, y+rectHeight, y}; 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 36 

g.drawPolygon(x1Points, y1Points, x1Points.length);  
... 

// Metoda: drawPolyline(xPoints, yPoints, numPoints)  
// Rysuje krzywą otwartą 

int x2Points[] = {x, x+rectWidth, x, x+rectWidth}; 
int y2Points[] = {y, y+rectHeight, y+rectHeight, y}; 
g.drawPolyline(x2Points, y2Points, x2Points.length);  
... 

// Metoda: fillRect(x, y, w, h) 

g.fillRect(x, y, rectWidth, rectHeight); 
... 

// Metoda: fill3DRect(x, y, w, h, raised)  

g.setColor(fg3D); 
g.fill3DRect(x, y, rectWidth, rectHeight, true); 
g.setColor(fg); 
... 

// Metoda: fillRoundRect(x, y, w, h, arcw, arch) 

g.fillRoundRect(x, y, rectWidth, rectHeight, 10, 10); 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 37 

... 

// Metoda: fillOval(x, y, w, h) 

g.fillOval(x, y, rectWidth, rectHeight); 
... 

// Metoda: fillArc(x, y, w, h, startAngle, arcAngle)  

g.fillArc(x, y, rectWidth, rectHeight, 90, 135); 
... 

// Metoda: fillPolygon(xPoints, yPoints, numPoints)  

int x3Points[] = {x, x+rectWidth, x, x+rectWidth}; 
int y3Points[] = {y, y+rectHeight, y+rectHeight, y}; 
g.fillPolygon(x3Points, y3Points, x3Points.length);  
... 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 38 

2) Rysowanie tekstu 

Funkcjonalno

ść

  dla  rysowanie  tekstu  w  AWT  zapewniaj

ą

  klasy

 

Graphics, Font, FontMetrics

W miar

ę

 mo

Ŝ

liwo

ś

ci nale

Ŝ

y korzysta

ć

 z komponentów stworzonych dla 

reprezentacji informacji tekstowej. 

 

W klasie

 Graphics

 

zdefiniowano trzy metody rysowania tekstu: 

drawBytes, drawChars, drawString.  

Np. 

g.drawString("Hello World!", x, y); 

Argumenty (liczby całkowite) x, y – pozycja lewego dolnego rogu tekstu 
(y wyznacza bazow

ą

 lini

ę

 tekstu). 

 

 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 39 

Klasa FontMetrics - 

umoŜliwia zmianę domyślnej czcionki. 

Przykład  8.9

.  Program  jest  modyfikacją  poprzedniego  programu  (8.8)- 

wykorzystano  obiekt  klasy  FontMetrics  dla  zmiany  rozmiaru  czcionki  tak, 
aby  najdłuŜszy  napis  („drawRoundRect”)  zmieścił  się  w  obszarze  dla 
pojedynczego kształtu. 

 

boolean fontFits = false; 
Font currentFont = biggestFont; 
FontMetrics currentMetrics = getFontMetrics(currentFont); 
int size = currentFont.getSize();  
String name = currentFont.getName(); 
int style = currentFont.getStyle(); 
                     
while (!fontFits) { 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 40 

    if ( (currentMetrics.getHeight() <= maxCharHeight) 
      && (currentMetrics.stringWidth(longString) <= xSpace)) {  
         fontFits = true; 
    } else { 
          if (size <= minFontSize) { 
              fontFits = true; 
          } else {  currentFont = new Font(name, style, --size); 
                       currentMetrics = getFontMetrics(currentFont); 
                   } 
       } 

Obiekt  klasy  FontMetrics  udostępnia  następującą  informację  o  rozmiarach 
danej czcionki: 

 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 41 

Metody klasy FontMetrics

 informujące o pionowych rozmiarach: 

int getAscent() 
int getMaxAscent()  

Pierwsza metoda podaje liczbę pikseli pomiędzy linią górną a bazową. Druga 
- maksymalną odległość dla najwyŜszych znaków. 

 

int getDescent() 
int getMaxDescent()  

Pierwsza  metoda  podaje  liczbą  pikseli  pomiędzy  linią  bazową  a  linią  dolną. 
Druga – maksymalna odległość dla najwyŜszych znaków. 

 

int getHeight();

 Metoda podaje liczbą pikseli pomiędzy linią bazową wiersza 

tekstu a linią bazową następnego wiersza tekstu. 

 

int getLeading()

Metoda podaje liczbą pikseli odstępu pomiędzy sąsiednimi 

wierszami  tekstu  –  pomiędzy  linią  dolną  jednego  wiersza  a  linią  dolną 
nastepnego. Do oznaczenia wysokości czcionki stosuje się miarę „punktową” 
– 1 punkt to ok. 1/72 cala. 

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 42 

Metody  klasy 

FontMetrics

  informujące  o  rozmiarach  w  poziomie  dla  czcionki 

(podają one szerokość czcionki z uwzględnieniem odstępu): 

 

int getMaxAdvance()  

Pełna szerokość (w pikselach) najszerszego znaku czcionki. 

 

int bytesWidth(byte[], int, int)  

Pełna  szerokość  tekstu  -  wycinka  tablicy  (1-szy  argument)  od  podanego 
indeksu (2-gi argument) i o podanej liczbie bajtów (3-ci argument). 

 

int charWidth(int) 
int charWidth(char)

Pełna szerokość podanego znaku. 

 

int charsWidth(char[], int, int)  

Pełna szerokość napisu – wycinka tablicy znaków. 

 

int stringWidth(String)

Pełna szerokość podanego napisu. 

 

int[] getWidths()  

Pełna szerokość kaŜdego z pierwszych 256 znaków czcionki. 

background image

8. Multimedia. 

W. Kasprzak: Programowanie zdarzeniowe 

8 - 43 

3) Klasa 

Graphics2D

 

Jest  to  znacznie  bogatsza  w  kształty  geometryczne  klasa  graficzna 
wprowadzona w Java 2. UmoŜliwia ona: 



 

rysowanie linii o dowolnej grubości; 



 

wypełnianie kształtów gradientami i teksturami; 



 

przesuwanie, obracanie i skalowanie oraz łączenie tekstu i grafiki; 



 

komponowanie przesłaniania tekstu i grafiki; 



 

zapamiętywanie obrazów i operacje na obrazach. 

Np.