Dione
Z. KotalaP. Toman: Java
Predchozi (Obsah) Dalsi

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.

appx256.gif

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:

Bohužel, Váš applet nespouští Javu.


  • (1) Podrobný popis knihovny AWT obsahují [CW97] a [JDK97].
  • (2) V případě appletu je kontejnerem už sám applet - aplikace musí vytvořit instanci třídy Frame (viz příklad A.1.).
  • (3) Přesné rozlišení typů událostí obsahuje [JDK97].

Predchozi
Converted by Selathco v0.9 on 25.09.1999 19:46
Dalsi