A. Abstract Window Toolkit (AWT)
Abstract Window Toolkit (AWT) (1) je část Java Core API, kterou
tvoří balíky:
- java.awt,
- java.awt.event (od JDK 1.1),
- java.awt.image,
- java.awt.datatransfer (od JDK 1.1).
AWT umožňuje tvorbu grafického uživatelského rozhraní (GUI), tj. práci
se vstupy a výstupy v graficky orientovaných systémech (Windows95/NT,
X Window). Programy využívající AWT jsou v duchu jazyka Java plně
přenositelné, ale zároveň je ovládání a vzhled jednotlivých prvků GUI, komponent, přizpůsobeno zvyklostem konkrétního systému.
Na následujícím obrázku je zachycen applet v prostředí X Window - tentýž
applet běžící pod Windows95 je na str. 3.  Každá komponenta - plátno (Canvas), výběr (Choice), nápis (Label), panel (Panel), seznam (List), textové pole (TextField) - je instancí příslušné třídy komponent z AWT.
A.1. Komponenty
GUI programu tvoří komponenty. Strom tříd komponent v java.awt vypadá
takto:
Component
|
+- Button
+- Canvas
+- Checkbox
+- Choice
+- Container
| |
| +- Panel
| | |
| | +---- java.applet.Applet (!!)
| |
| +- ScrollPane
| +- Window
| |
| +- Dialog
| | |
| | +- FileDialog
| +- Frame
+- Label
+- List
+- Scrollbar
+- TextComponent
|
+- TextArea
+- TextField
Nejdůležitější jsou rodičovské třídy komponent a kontejnerů:
- Abstraktní třída Component definuje metody pro zobrazení grafické
komponenty a zpracování (v JDK1.0) a zasílání (v JDK1.1) událostí (viz
dále).
- Abstraktní třída Container definuje metody pro přidávání,
odebírání a manipulaci s komponentami - instance potomků této třídy mohou
vlastnit další komponenty.
Způsob rozložení komponent v kontejneru určují layout managery -
instance tříd: BorderLayout, CardLayout, FlowLayout,
GridBagLayout, GridBagConstraints, GridLayout.
Samozřejmě je možné si navrhnout vlastní manažer. Činnost programu využívajícího komponenty je následující: program vytvoří
kontejner (2) , do kterého následně může přidávat další komponenty.
Tím se vytvoří hierarchie instancí komponent, která pro předchozí obrázek
appletu vypadá takto:
Panel
|
+--------+--------+------+---------+
| | | | |
Canvas Label Choice List TextField
Při vykreslování se postupuje shora dolů; pořadí vykreslování komponent na
stejné úrovni není definováno. Program reaguje na pokyny uživatele tím, že jednotlivé komponenty zachycují
události (vstupy z klávesnice a myši) a na základě nich se vykonává
další činnost.
A.2. Zpracování událostí
Způsob předávání a zpracování událostí se v JDK 1.1 zásadně liší od JDK 1.0,
neboť starý způsob byl "shledán těžkopádným". Kombinování obou
způsobů se nedoporučuje. Kromě akcí, které uživatel vyvolává přímo (pohyb
myši, stisk klávesy) se za událost považuje i například otevření okna,
výběr položky v menu apod. (3)
- JDK 1.0 - pokud nastane libovolná událost, vytvoří se instance třídy
java.awt.Event. Tato instance se propaguje zdola nahoru hierarchií
komponent, počínaje komponentou, nad níž událost nastala - u každé
komponenty se volá metoda handleEvent() s parametrem instance události.
- JDK 1.1 - o nastalé události jsou informovány jen ty objekty (nemusí
jít pouze o komponenty), které o to požádají (zaregistrují se). O jedné
události (instanci třídy java.util.EventObject) může být informováno
i více objektů nebo také žádný.
Události se dělí do několika tříd definovaných v balíku java.awt.event:
- ActionEvent - nastane při stisku tlačítka apod.,
- KeyEvent - nastane při stisku klávesy,
- MouseEvent - nastane při pohybu myši, stisknutí tlačítka myši
apod.,
- WindowEvent - nastane při otevření, zavření okna apod.
- ...
A.3. Výstup grafiky
Grafický kontext neboli oblast, kam je možné provádět grafický výstup,
reprezentují instance třídy java.awt.Graphics. Tato třída definuje
metody pro kreslení grafických primitiv (čára - drawLine(), ovál - drawOval(), polygon - drawPolygon() apod.), výstup textu - drawString(), vykreslení obrázku - drawImage() atd.Grafický kontext má přiřazen každá zobrazená komponenta - výstup do jejího
kontextu se provádí v metodách update(java.awt.Graphics g) a paint(java.awt.Graphics g). Manipulaci s obrázky (včetně načítání formátu GIF a JPEG) slouží třídy
z balíku java.awt.image a třída java.awt.Image. K vytváření animací je zapotřebí vláken, viz příklad 16.2..
Priklad A.1. |
Následující program demonstruje použití AWT. Obsahuje dvě
komponenty: plátno (potomka třídy java.awt.Canvas), které umožňuje
kreslení pomocí myši, a tlačítko "Clear", které plátno vymaže. Program
funguje jako applet i jako aplikace. Události zpracovává s využitím modelu
podle JDK 1.1.
Dokumentace vygenerovaná z komentářů programem javadoc je
zde.
package demo;
import java.applet.Applet;
import java.awt.event.*;
import java.awt.*;
/**
* Hlavní třída programu SimpleDraw .
* @author Petr Toman
* @version JDK 1.1
*/
public class SimpleDraw extends java.applet.Applet {
/**
* Metoda init() se volá, je-li program spuštěn jako applet.
* @see java.awt.Frame
* @see java.awt.Button
* @see java.awt.Canvas
*/
public void init() {
// vytvoření plátna -- plochy pro kreslení
PaintCanvas paintCanvas = new PaintCanvas();
// vytvoření tlačítka s nápisem "Clear"
Button button = new Button("Clear");
// registrace plátna jako příjemce události při stisku tlačítka
button.addActionListener(paintCanvas);
// nastavení layout manageru
setLayout(new BorderLayout());
// vložení plátna a tlačítka "Clear" do appletu-kontejneru
add(paintCanvas, "North");
add(button, "South");
}
/**
* Metoda main() se volá, je-li program spuštěn jako aplikace.
* Provádí totéž, co init() , pouze nejprve vytvoří okno ( frame ),
* do kterého umisťuje komponenty.
* @param args parametry příkazové řádky (nepoužito)
*/
public static void main(String[] args) {
Frame frame = new Frame("SimpleDraw");
PaintCanvas paintCanvas = new PaintCanvas();
Button button = new Button("Clear");
button.addActionListener(paintCanvas);
frame.add(paintCanvas, "North");
frame.add(button, "South");
frame.pack();
frame.show();
}
}
/**
* Třída sloužící pro vytvoření plátna. Zachycuje události "pohyb myši"
* a "stisk tlačítka" -- proto implementuje uvedená rozhraní.
* @see java.awt.event.MouseMotionListener
* @see java.awt.event.ActionListener
*/
public class PaintCanvas extends Canvas
implements MouseMotionListener, ActionListener {
Graphics offGraphics; // skrytý grafický kontext
Image offImage; // skrytý obrázek (buffer)
int oldx, oldy; // "staré" souřadnice myši
/** Konstruktor */
public PaintCanvas() {
// nastavení barvy pozadí na bílou
setBackground(Color.white);
// registrace sebe ( this ) jako příjemce události "pohyb myši"
addMouseMotionListener(this);
}
/**
* Metoda getMinimumSize() musí být implementována kvůli
* určení velikosti pro layout manager.
* @return minimální velikost komponenty (plátna).
*/
public Dimension getMinimumSize() {
return new Dimension(300,200);
}
/**
* Metoda getPreferredSize() musí být implementována kvůli
* určení velikosti pro layout manager.
* @return preferovanou velikost komponenty (plátna).
*/
public Dimension getPreferredSize() {
return getMinimumSize();
}
/**
* Metoda mouseDragged() je volaná při pohybu a současném držení
* tlačítka myši.
*/
public void mouseDragged(MouseEvent e) {
// je-li možno provádět výstup, vykreslí čáru
if (offGraphics != null)
offGraphics.drawLine(oldx, oldy, e.getX(), e.getY());
// uschování souřadnic myši
oldx = e.getX();
oldy = e.getY();
// překreslit plátno!
repaint();
}
/**
* Metoda mouseMoved() je volaná při pohybu myši (bez stisku tlačítka).
*/
public void mouseMoved(MouseEvent e) {
// uschování souřadnic myši
oldx = e.getX();
oldy = e.getY();
}
/**
* Metoda actionPerformed() je volaná stisku tlačítka "Clear".
*/
public void actionPerformed(ActionEvent e) {
// zrušení skrytého bufferu (bude provedeno vymazání)
offImage = null;
// překreslit plátno!
repaint();
}
/**
* Metoda update() je volána při překreslování komponenty.
* Standardně vymaže pozadí a volá metodu paint() .
* Je předefinována, aby nedocházelo k blikání.
*/
public void update(Graphics g) {
paint(g);
}
/**
* Metoda paint() provádí vykreslení obsahu plátna -- překopíruje
* skrytý buffer do grafického kontextu komponenty ( parametr g ).
*/
public void paint(Graphics g) {
int width = getSize().width;
int height = getSize().height;
if (offImage == null) {
// vytvoření prázdného bufferu
offImage = createImage(width, height);
offGraphics = offImage.getGraphics();
}
// nastala změna velikosti komponenty?
if (offImage.getWidth(this) != width ||
offImage.getHeight(this) != height) {
// ano - vytvořit skrytý buffer aktuální velikosti...
Image img = createImage(width, height);
offGraphics = img.getGraphics();
// ... a zkopírovat starý buffer
offGraphics.drawImage(offImage,0,0,this);
offImage = img;
}
// zobrazení bufferu do grafického kontextu komponenty
g.drawImage(offImage,0,0,this);
}
}
Pro applet je třeba vytvořit HTML dokument, který obsahuje text:
<APPLET
CODE = demo.SimpleDraw.class
WIDTH = 300
HEIGHT = 230>
</APPLET>
Vlastní applet pak vypadá takto: |
---|
|
|
|
|