Adam Lipowski

Programowanie strukturalne w Javie

Oblicz przybliżenie liczby e   =  1/0!+1/1!+1/2!+...


/*

 * EComputation.java by Richard J. Davies
 * from `Introductory Java for Scientists and Engineers'
 * This program computes e by summing its series expansion.
 * Note that we use a method call to initialize the constant E.
 */
public class EComputation
{
  // The number of terms to be added up.
  public static final int TERMS = 20;
  public static final double E = computeE();    // Inicjalizacja stałej za pomocą wywołania metody!
  public static double nextTerm(double prev,
                                int index)
  {
    return prev/index;
  }
  public static double computeE()
  {
    double res = 1;
    double term = 1;
   
    for (int i=1; i<TERMS; i++)
    {
      term = nextTerm(term, i);
      res += term;
    }

    return res;
  }
  public static void main(String[] argv)
  {
    System.out.println(E);
  }
}



Klasy i Metody


Zadania obiektu:
- zamknięcie danych w pewną (odizolowaną) całość
- ogólny charakter dopuszcza wykorzystanie w wielu sytuacjach
- baza do konstrukcji innych obiektów (dziedziczenie)

Deklaracja class definiuje obiekty

Przykład1. Klasa Complex

public class Complex{

    public double realpart;
    public double imagpart;
}

Zmienne realpart i imagpart nie mają specyfikatora static. Istnienieją one tylko w kontekście jakiegoś obiektu klasy Complex. Są to tzw. pola obiektu.

public static void main(String [] argv){
    Complex a;
     a=new Complex();
      a.realpart = 1.0;
      a.imagpart=3.4;
}

Metoda statyczna mnożąca liczbę zespoloną przez rzeczywistą:

public static Complex scalarMultiply(Complex c, double s){
      Complex ans = new Complex();
      ans.realpart=c.realpart*s;
      ans.imagpart=c.imagpart*s;
      return ans;
}

Wykorzystanie: 

            c= scalarMultiply(c,2.7);

Równoważnie, możemy utworzyć metodę niestatyczną

             public void scalarMultiply(double s);

którą wywoływalibyśmy jako

                c.scalarMultiply(2.7);

Definicja tej metody jest następująca:

public void scalarMultiply(double s) {
    this.realpart=this.realpart*s;
    this.imagpart=this.imagpart*s;
}

this to referencja do obiektu (klasy Complex) na rzecz którego wywoływaliśmy metodę. W tym przypadku możemy opuścić this:

public void scalarMultiply(double s) {
    realpart=realpart*s;
    imagpart=imagpart*s;
}
 
Konstruktor - specjalna metoda nie zwracająca wyniku (nawet typu void ), służąca do konstrukcji obiektu w oparciu o ewentualne parametry.

public Complex(double r, double i){
      realpart=r;
      imagpart=i;
}

Klasa Complex z konstruktorami (zero- i dwuargumentowym) oraz niestatycznymi metodami add oraz multiply:

/*
 * Complex.java by Richard J. Davies
 * from `Introductory Java for Scientists and Engineers'
 * This program implements a class `Complex' with non-static members and so
 * enables us to create objects of a new `Complex' data type. It is only an
 * example and does not implement all of the features that you would want from
 * a complex number. See `JNL, a Numerical Library for Java' from a fuller
 * class. This is intended as a first example of an object that we ourselves
 * have written.
 */
public class Complex
{
  // Declare the data variable for the type
  public double realpart;
  public double imagpart;

  // Default constructor sets value to 0 + 0i
  public Complex()
  {
    realpart = 0;
    imagpart = 0;
  }

  // Constructor with user specified value
  public Complex(double r, double i)
  {
    realpart = r;
    imagpart = i;
  }

  // Method to add `other' to this object
  public void add(Complex other)
  {
    realpart += other.realpart;
    imagpart += other.imagpart;
  }

  // Method to multiply `other' into this object
  public void multiply(Complex other)
  {
    // Declare temporary storage for calculation
    Complex ans = new Complex();

    // Calculate
    ans.realpart = realpart * other.realpart
                   - imagpart * other.imagpart; 
    ans.imagpart = realpart * other.imagpart
                   + imagpart * other.realpart;

    // Copy value into this object.
    realpart = ans.realpart;
    imagpart = ans.imagpart;
  }

  // Main method. Static and so independent
  // of the definition of the object type.
  public static void main(String[] argv)
  {
    // Declare and create some objects
    Complex a = new Complex();
    Complex b = new Complex(4.7, 3.2);
    Complex c = new Complex(3.1, 2.4);

    // Perform some arithmetic
    a.add(b);
    c.multiply(a);

    // Extract the answer
    System.out.print(c.realpart + " + ");
    System.out.println(c.imagpart + "i");
  }
}


Definicja klasy:

class nazwa {
       deklaracje pól
       konstruktor
       metody
}

System.out.println(...)

public class System {    // klasa system pakietu java.lang
    .....
    public static PrintStream out;  // pole statyczne klasy PrintStream (związane za standardowym wyjściem)
    ....
}

public class PrintStream {    // klasa pakietu java.io
    .....
    public void println (String s){  // metoda, która wypisuje na stdout wiersz podany jako argument
    ......
    }
}

System.out - statyczne pole klasy System o identyfikatorze out , oznaczające obiekt klasy PrintStream
println - użycie metody na rzecz tego obiektu



Przykład 2. Klasa Time
Zadanie: zdefiniować klasę Time reprezentującą godziny i minuty. Z użyciem tej klasy będziemy chcieli np. drukować aktualny czas lub dodawać pewną liczbę minut.

Przykładowe wykorzystanie:
class Schedule{
   public static void main(String[] args){
   Time start= new Time(8,30);  
   start.printTime();
   System.out.println("--------------");
   start=start.addMinutes(30);
    start.printTime();
   System.out.println("--------------");
   }
}

Definicja klasy
Time
class Time{
private int hour,minute;  // pola obiektu są dostępne tylko wewnątrz klasy Time
   public Time (int h, int m){hour=h;minute=m;} // Konstruktor obiektu
   public Time addMinutes(int m) {
      int totalMinutes=(60*hour+minute+m)%(24*60);
      if(totalMinutes<0)
         totalMinutes=totalMinutes+24*60;
      return new Time(totalMinutes/60,totalMinutes%60);
}
   public void printTime(){
       if ((hour == 0) && (minute == 0))
                   System.out.print("midnight");
       else if ((hour == 12) && (minute == 0))
                   System.out.print("noon");
       else {
           if (hour==0) System.out.print(12);
           else if (hour>12) System.out.print(hour-12);
           else System.out.print(hour);
           if(minute<10) System.out.print(":0"+minute);
           else System.out.print(":"+minute);
           if(hour<12) System.out.print("AM");
           else System.out.print("PM");
      }
   }
}
Przeciążenie konstruktora:

Dopuszczalne jest wprowadzenie większej liczby konstruktorów, które różnią się
liczbą   argumentów bądź ich typem.

class Time{
private int hour,minute;
   public Time (int h, int m){hour=h;minute=m;}
   public Time (){hour=0;minute=0;}
   public Time (int m){hour=m/60;minute=m%60;}
   public Time addMinutes(int m) {...}
   public void printTime(){...}

Można wówczas definiować obiekty w następujący sposób:
Time t1=new Time(), // Nawias jest konieczny!
         t2=new Time(720),
         t3=new Time(525);
Co jest równoważne:
Time t1=new Time(0,0),
         t2=new Time(12,0),
         t3=new Time(8,45);

Uwaga: w analogiczny sposób można przeciążać metody.

Metoda odejmowania m minut:

public Time subtractMinutes(int m) {
return addMinutes(-m);
}

W konstrukcji tej   odwołujemy się do metody addMinutes z pominięciem adresata
(receiver-of-subtractMinutes.addMinutes(-m)). Jest to możliwe, gdyż addMinutes i
subtractMinutes   są metodami tej samej klasy  (Time) i wywoływane są z tymi samymi
adresatami.


Z użyciem this, metodę subtractMinutes można napisać następująco:
public Time subtractMinutes(int m) {
return this.addMinutes(-m);
}
Metody porównywania czasów:

`Być wcześniej` 
/* Metoda sprawdza czy obiekt, na rzecz którego
wywołaliśmy metodę jest wcześniej niż argument metody */
public boolean priorTo (Time t) {
   return ((hour<t.hour) || ((hour==t.hour)&&(minute<t.minute)));
}

Przykład:
Time t1= new Time(8,30);
Time t2= new Time(8,50);
........
boolean   ifbefore=t1.priorTo(t2);

Być później’
public boolean after (Time t2) {
   return t2.priorTo(this);
}

this – pozwala odwołać się wewnątrz metody do ‘adresata’   tej metody.

Dziedziczenie Klas

Dziedziczenie (inheritance) klas pozwala  dostosować istniejącą już klasę do własnych potrzeb. Własność ta jest jedną z największych zalet języków obiektowych. Załóżmy, że istnieje już pewna klasa, która posiada prawie komplet wymaganych przez nas własności. Zamiast tworzyć nową klasę od początku, używamy dziedziczenia aby dodać do istniejącej klasy brakujące cechy.

syntaktyka dziedziczenia:       derived-class extends  base-class

Przykład 1
Załóżmy, że chcemy napisać program przechowujący informację o studentach: nazwisko, wiek, PESEL, kierunek studiów i średnia ocen. Chcemy wykorzystać istniejącą już klasę Person reprezentującą ludzi, która zawiera informacje takie jak: nazwisko, wiek i PESEL.

public class Person{              // klasa bazowa

    private String nazwisko;
    private int wiek;
    private String pesel;
    public  Person (String n, int w, String p){
               nazwisko=n;
               wiek=w;
                pesel=p;
    }
    public void printPerson(){
           System.out.println("Nazwisko: "+nazwisko);
           System.out.println("Wiek: "+wiek);
           System.out.println("PESEL: "+pesel);
    }
}


public class Student extends Person{          // klasa pochodna (dziedzicząca)
      private String kierunek;
      private double srednia;
      public Student(String n, int w, String p, String k, double av){
              super(n,w,p);   // konstruktor klasy bazowej (Person)
              kierunek=k;
              srednia=av;
     }
     public void studentInfo(){
            printPerson();  // metoda z klasy bazowej;
            System.out.println("Kierunek: "+kierunek);
          
System.out.println("Średnia: "+srednia);
    }
}

Przykład 2
Chcemy rozszerzyć klasę Time , aby uwzględniała sekundy.

Klasa bazowa
class Time{
private int hour,minute;  // pola obiektu są dostępne tylko wewnątrz klasy Time
   public Time (int h, int m){hour=h;minute=m;} // Konstruktor obiektu
   public void advanceMinutes(int m) {       // modyfikacja - metoda typu void
      int totalMinutes=(60*hour+minute+m)%(24*60);
      if(totalMinutes<0)
         totalMinutes=totalMinutes+24*60;
      hour=totalMinutes/60;
      minute=totalMinutes%60);
}
   public void printTime(){
       if ((hour == 0) && (minute == 0))
                   System.out.print("midnight");
       else if ((hour == 12) && (minute == 0))
                   System.out.print("noon");
       else {
           if (hour==0) System.out.print(12);
           else if (hour>12) System.out.print(hour-12);
           else System.out.print(hour);
           if(minute<10) System.out.print(":0"+minute);
           else System.out.print(":"+minute);
           if(hour<12) System.out.print("AM");
           else System.out.print("PM");
      }
   }
}
Klasa pochodna
class PreciseTime extends Time{
    private int second;
    public PreciseTime(int h, int m, int s){
         super(h,m);   // wywołanie konstruktora klasy Time
         second = s;
   }
   public void advanceSeconds(int s){
         int advMinutes = s/60;
         second+=s%60;
         if(second<0){
              advMinutes--;
               second+=60;
         }
         else if
(second>=60){
              advMinutes++;
               second-=60;
         }
         advanceMinutes(advMinutes);
  }
}

Wykorzystanie

public class Tme1Mutate{
   public static void main(String [] args){
         PreciseTime lunchtime = new PreciseTime(13,10,0);
         lunchtime.advanceSeconds(60);
         lunchtime.printTime();System.out.println();
        lunchtime.advanceSeconds(-61);
        lunchtime.printTime();System.out.println();

  }
}

Wydruk:

 1:11PM
 1:09PM

printTime na obiektach klasy PreciseTime działa dokładnie tak samo jak obiektach klasy Time: wypisuje godziny i minuty.
Załóżmy, że w klasie PreciseTime chcemy zdefiniować nową metodę printTime:

public void printTime(){
       if ((hour == 0) && (minute == 0))
                   System.out.print("midnight");
       else if ((hour == 12) && (minute == 0))
                   System.out.print("noon");
       else {
           if (hour==0) System.out.print(12);
           else if (hour>12) System.out.print(hour-12);
           else System.out.print(hour);
           if(minute<10) System.out.print(":0"+minute);
           else System.out.print(":"+minute);
           if(second<10) System.out.print(":0"+second);
           else System.out.print(":"+second);
           if(hour<12) System.out.print("AM");
           else System.out.print("PM");
      }
   }

Metoda ta nie zadziała. Z klasy PreciseTime nie mamy dostępu do prywatnych pól klasy Time. Należy w klasie Time zmienić specyfikator private na protected:

class Time{
protected int hour,minute; 
....

Specyfikator protected udostępnia dane pole klasom pochodnym ale nie klientom.

Dynamiczne wiązanie (Dynamic binding)

Zarówno w klasie Time jak i w klasie PreciseTime mamy zdefiniowane metody PrintTime. Rozważmy konstrukcję:

Time dawn;
dawn = new PreciseTime(3,45,30);
dawn.PrintTime();

Pytanie: Z której klasy zostanie wywołana metoda PrintTime ?
Obiekt dawn jest klasy Time, ale zawiera referencję do klasy PreciseTime.
Odpowiedź: z klasy PreciseTime. Wywołana metoda zależy od klasy słuchacza ( receiver) metody.

Zwykle, to która metoda będzie wywołana można wyznaczyć bez uruchamiania programu (w fazie kompilacji). Jest to tzw. wiązanie statyczne. Jednakże, gdy metoda jest przedefiniowana w podklasie, to reguła ta nie jest spełniona i w Javie stosuje się tzw. wiązanie dynamiczne.

Załóżmy, że istnieją dwie podklasy: PreciseTime i PreciseTime1 ;

     Time dawn;
      if(arg[0].equals("A")) dawn= new PreciseTime(3,45,30); // arg[0] - pierwszy parametr
           else dawn=
new PreciseTime1(4,25,50);
     dawn.PrintTime();

Jest oczywiste, że w tym przypadku wyznaczenie klasy słuchacza może się odbyć wyłącznie w fazie uruchamiania programu.

Interfejsy

Wielodziedziczenie może niekiedy prowadzić do pewnych niejednoznaczności np. dotyczących przynależności pól.

class A {
 int a;
........
}
class B extends A { // ma pole a
........
}
class C extends A { // ma pole a
........
}

class D extends B i C { //  hipotetyczne wielodziedziczenie
........
}

Obiekt d z klasy D ma pole a. Jedno czy dwa? Jeżeli tak to które? Co oznacza odwołanie d.a?
W Javie zrezygnowano z koncepcji wielodziedziczenia. Zamiast tego wprowadzono pojęcie interfejsu jako klasy nie zawierającej pól, a tylko metody (publiczne i abstrakcyjne) i ewentualnie stałe statyczne.
Interfejs daje więc możliwość definiowania zachowania się obiektów bez określania jak to zachowanie będzie implementowane.

Przykład Interfejs Shape
Interfejs ten zawiera dwie metody typowe dla obiektów posiadających kształt: area i circumference:

public interface Shape{
    public double area();
    public double circumference();

    public static final double PI = 3.14159;
}

Dwa przykładowe kształty, które mogą implementować ten interfejs to Circle i Rectangle. Aby klasa mogła implementować intefejs, musi ona specyfikować jego metody.

public class Circle implements Shape{
      private double radius;
      public Circle (double r) {radius = r;}
      public double area(){
             return PI*radius*radius;
      }
      public double circumference(){
             return 2*PI*radius;
      }

}

public class Rectangle implements Shape{
      private double height;
      private double width;
      public Rectangle (double h, double w) {height=h; width=w}
      public double area(){
             return height*width;
      }
      public double circumference(){
             return 2*(height+width);
      }

}

Wykorzystanie

public class TestShapes{
     public static void display(Shape figure){
          System.out.println("The area is "+figure.area());
          System.out.println("The circumference is "+figure.circumference());
    }
    public static void main(String args[]){
          Shape figOne = new Circle(3.5);
          display(figOne);

          Shape figOne = new Rectangle(3.2,5.1);
          display(figOne);

    }
}

- W tym przykładzie figOne jest referencją polimorficzną.
- Metody interfejsu domyślnie są traktowane jako typ abstract (tzn. są niezdefiniowane).
- W klasach abstrakcyjnych część metod może być zdefiniowana a część nie.
- Implementacja interfejsów odgrywa ważną rolę w Javie: obsługa zdarzeń, tworzenie wątków,...

Obsługa zdarzeń i komponenty AWT

Słuchacz to obiekt, który może obsługiwać zdarzenia (wciśnięcie guzika, przesunięcie myszki lub suwaka, wpisanie tekstu, itp.). Aby móc generować obiekty-Słuchaczy, klasa musi implementować interfejs nasłuchu. Tzn., metody interfejsu nasłuchu muszą zyskać konkretne definicje.

Zdarzenia przytrafiają się obiektom. Obiekt, któremu przytrafiło sie zdarzenie nazywany jest źródłem (source). Zdarzenie do obsługi przekazywane jest ze źródła do słuchacza tylko wtedy, gdy do danego źródła przyłączony jest słuchacz reagujący na ten typ zdarzenia. Przyłączenia dokonujemy za pomocą odwołania:

z.addxxxListener(l);

gdzie  z - źródło ,  xxx - rodzaj nasłuchiwanych zdarzeń ( Action, Item,Adjustement, MouseMotion), l - słuchacz.

ActionEvent to klasa zdarzeń oznaczających wykonanie akcji. Słuchacz akcji (obiekt klasy, która ma ją obsługiwać) musi implementować interfejs ActionListener i zdefiniować metodę actionPerformed  tego interfejsu.

AWT - Abstract Windowing Toolkit
Jest to zbiór klas zapewniających tworzenie prostych elementów graficznego interfejsu  użytkownika ( applet, Label, Button, TextField, ...). Znajdują się one w pakiecie java.awt (wymagany import).

Konwersja temperatury - Aplet

import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class TempApplet1 extends Applet implements ActionListener {
    TextField tFahr;
    Label lCent;
    public void init(){
       tFahr=new TextField(10);
       lCent=new Label ("I'll tell you what that is in degrees C");
       add (new Label("Please type the temperature (deg F)"));
       add(tFahr);
       add(lCent);      
       tFahr.addActionListener(this);
    }
    public void actionPerformed(ActionEvent e){
    int fahr=0,
           cent=0;
    fahr=Integer.parseInt(tFahr.getText());
    cent=(int)(5.0*(fahr-32)/9.0);  
    lCent.setText(fahr+" deg F is "+cent+" deg C");
    }
}




Dwustronna konwersja temperatury - Aplet

import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class TempApplet2 extends Applet implements ActionListener {
    TextField tFahr=new TextField(9),
              tCent=new TextField(9);
    public void init(){
       add (new Label("Fahrenheit"));
       add(tFahr);
       add(new Label("Centigrade"));      
       add(tCent);
       tFahr.addActionListener(this);
       tCent.addActionListener(this);
    }
    public void actionPerformed(ActionEvent e){
       int fahr,cent;
       if(e.getSource()==tFahr){         //   rozróżnienie źródła akcji
          fahr=Integer.parseInt(tFahr.getText());
          cent=(int)(5.0*(fahr-32)/9.0);
          tCent.setText(cent+"");
       }
       else{
          cent=Integer.parseInt(tCent.getText());
          fahr=(int)(9.0*cent/5.0+32.0);
          tFahr.setText(fahr+"");
       }
    }
}

Podobna obsługa zdarzeń jest możliwa w klasie Button

StartStop-PrawoLewo - Aplet

import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class startstop extends Applet implements ActionListener {
    Button b1 = new Button("Start");
    Button b2 =new Button("Prawo");
    Label la;
    public void init(){          
       la=new Label("Nacisnij przycisk");
       add(la);
       add(b1);
       add(b2);
       b1.addActionListener(this);
       b2.addActionListener(this);
    }
    public void actionPerformed(ActionEvent e){
        String txt;
    if(e.getSource()==b1){
       if(b1.getLabel()=="Stop"){
          b1.setLabel("Start");
       }
       else{
           b1.setLabel("Stop");
       }  
       la.setText("nacisnales 1");
    }
    else{
       if(b2.getLabel()=="Prawo"){
          b2.setLabel("Lewo");
       }
       else{
           b2.setLabel("Prawo");
       }  
       la.setText("nacisnales 2");
    }
    }
}

Button
i TextField to przykłady tzw. komponentów.  Inne komponenty to np. MenuItem, Choice, Checkbox, Scrollbar. Komponenty te można związać  ze słuchaczami i metodami je obsługującymi.

Button
MenuItem
TextField
ActionListener
actionPerformed(ActionEvent e)
Choice
Checkbox
CheckboxMenuItem
ItemListener
itemStateChanged(ItemEvent e)
Scrollbar
AdjustementListener
adjustementValueChanged(AdjustementEvent e)


Metody obsługi zdarzeń zwracają wartość void.

Metoda getSource() służy do rozróżnienia źródła zdarzenia:
 
         public void actionPerformed(ActionEvent e){
         ....
         if (e.getSource() == TextField name) {...}
         ....
    
    if (e.getSource() == Button name) {...}
         ....
         }

Analogicznie obsługujemy zdarzenia np. dla  Checkbox. Interface ItemListener wymaga zdefiniowania metody itemStateChanged:

         public void itemStateChanged (ItemEvent e){
         ....
         if(e.getSource() == Checkbox name)   {...}
         ....
         }

Klasa może implementować kilku słuchaczy:

        public class My_applet extends Applet implements ItemListener, ActionListener {
        .....
        }

Komponenty

Komponenty wywodzą się z abstrakcyjnej klasy Component, która definiuje metody m.in. ustalające właściwości komponentów.Istnieją dwa rodzaje komponentów: kontenery (mogące zawierać inne komponenty) i komponenty terminalne.


Ogólne właściwości komponentów:

Rozmiar i położenie - zwykle ustalane przez zarządcę rozkładu (Layout Manager )

Pismo - obiekt klasy Font. Konstruktor Font (nazwa_pisma, styl, rozmiar)
            
nazwa_pisma = "Dialog", "DialogInput","Serif", "SansSerif",...
            
styl = Font.BOLD,
Font.ITALIC,Font.PLAIN
             rozmiar = liczba całkowita (wielkość w punktach)
               Button b = new Button ("Napis");
                 b.setFont(new Font("Serif", Font.BOLD, 16));

Kolor - obiekt klasy Color.
              b.setBackground(Color.red);
              b.setForeground(new Color(0,15,245)); 
             // (0,0,0) - czarny, (255,255,255) - biały, w ogólności:(red, green, blue)

Zablokowanie/odblokowanie
            b.setEnabled(false); // zablokowanie (nie reaguje na naciśnięcie guzika)      
            b.setEnabled(true);  // odblokowanie

Uwidacznianie - komponenty są domyślnie widoczne. W trakcie działania programu można je jednak uczynić niewidocznymi.
            b.setVisible(false); // stanie się niewidocznym
            if (!b.isVisible()) b.setVisible(true); // jeżeli niewidoczny to uwidaczniamy

Kontenery

Kontenery to komponenty, ktore moga zawierać inne komponenty (niekoniecznie terminalne).
Przykład
Button b1 = new Button ("Napis1");
Button b2 = new Button ("Napis2");
Panel p = new Panel();
  p.add(b1);
  p.add(b2);


Specjalizowany słuchacz akcji

Można zdefiniować słuchacza akcji jako obiekt odrębnej klasy.

import java.awt.*;
import java.applet.*;
import java.awt.event.*;
class SpecSluch implements ActionListener{
Button bc;
int i=0;
SpecSluch(Button b){bc=b;}
public void actionPerformed(ActionEvent e){
i++;
bc.setLabel(""+i);
}
}
public class test_SpecSluch extends Applet {
    Button b1 = new Button("guzik1");
    Button b2 =new Button("guzik2");
    public void init(){      
    add(b1);
    add(b2);
    b1.addActionListener(new SpecSluch(b1));
    b2.addActionListener(new SpecSluch(b2));
}
}

Dzięki takiej separacji upraszcza się metoda
actionPerformed.

Działanie
       
Zarządzanie wyglądem ekranu


Rozmieszczeniem komponentów wewnątrz apletu lub  kontenera zarządza Layout Manager.

Domyślnie używany jest FlowLayout manager, tzn. komponenty dodawane są w kolejności pojawiania się (add(...)), od strony lewej do prawej, od góry do dołu.

Inne możliwości to:

GridLayout(m,n)
- dzieli ekran (aplet lub kontener) na m wierszy i n kolumn.

BorderLayout() - ekran jest podzielony na 5 części: "North", "South", "East", "West" i "Center".
Dodawanie komponentu w tym przypadku odbywa się za pomocą dwuargumentowej metody, np.
              add("North", new Label("The Title"));

Zmianę sposobu rozmieszczenia osiągamy za pomocą komendy setLayout(...). Na przykład:
                 setLayout(new BorderLayout());

 
Aplet StartStop-PrawyLewy z użyciem BorderLayout może wyglądać tak .

Można rownież zarządać brak menadżera rozkładu: kontener.setLayout(null). W takim przypadku rozmiary i umiejscowienie komponentów musimy ustalić samodzielnie. Np . za pomocą metody setBounds(x,y,w,h), x,y - współrzędne położenia , w - szerokość, h - wysokość .