Graafisen käyttöliittymän laadintatekniikkaa

Swingin komponentteja

Ikkuna - JFrame
JFrame muodostaa pohjan muulle graafiselle käyttöliittymälle, johon muita komponentteja voidaan lisätä Alla oleva esimerkki luo tyhjän ikkunan. Ensimmäisellä rivillä luodaan ikkuna, toisella määritetään mitä tapahtuu kun ikkuna suljetaan. 3. rivillä sovitetaan ikkuna ja 4. rivillä asetetaan ikkunan näkyväksi. Yleensä luokka joka muodostaa graafisen käyttöliittymän, laajentaa (extends) JFrame-luokkaa.

	JFrame frame = new JFrame("Ikkuna");						
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);	
	frame.pack();											
	frame.setVisible(true);									
JFrame-luokan hierarkia Object-yliluokkaan nähden
	java.lang.Object
  -> java.awt.Component
    -> java.awt.Container
      -> java.awt.Window
        -> java.awt.Frame
          -> javax.swing.JFrame
Paneeli - JPanel
Toimii säiliönä muille graafisille komponenteille, sekä määrää sen miten komponentit asetellaan näkymään käyttäjälle. Paneeliin voidaan asettaa valittu layoutManager, jolla saadaan halutunlainen asettelu sille miten komponentit näkyvät paneelissa.

Esim. Luodaan paneeli ja asetetaan siihen GridLayout tyyppinen asemointi.
    buttonPanel = new JPanel();
    buttonPanel.setLayout(new GridLayout(4,4) );
Paneeliin voidaan lisätä komponentteja add() -metodilla
    buttonPanel.add(JButton);
Myös toisten paneeleiden lisääminen paneeliin on mahdollista
public CalculatorPanel() {
    setLayout(new BorderLayout() );
    ...
    // Lisätään painikepaneeli laskimen paneeliin.
    add(buttonPanel,"Center");
JPanel-luokan hierarkia Object-yliluokkaan nähden
java.lang.Object
  -> java.awt.Component
    -> java.awt.Container
      -> javax.swing.JComponent
        -> javax.swing.JPanel

Painonappi - JButton
Edellisessä esimerkissä käytetty painonappi muodostetaan JButton-luokalla
	Container container = getContentPane();
	container.add(new JButton("Nappula"));
JButton-luokan hierarkia Object-yliluokkaan nähden
	java.lang.Object
  -> java.awt.Component
    -> java.awt.Container
      -> javax.swing.JComponent
        -> javax.swing.AbstractButton
          -> javax.swing.JButton
Tekstikenttä - JTextField
Tässä komponentissa voidaan editoida yhtä rivillistä tekstiä. On kätevä mm. lomakkeisiin jossa pyydetään käyttäjältä jotain tietoja (nimi, osoite,..) tai vaikka näyttämään laskimen tekemät laskutoimitukset.

Esim. Luodaan laskimen näyttöä varten tekstiruutu ja asetetaan se sellaiseksi, että kentän sisältöä ei voida muuttaa:
    screen = new JTextField("");
    screen.setEditable(false);
Kentän sisältö voidaan hakea String-olioon getText -metodilla ja kenttään voidaan viedä teksti setText -metodilla.
screen.setText(screen.getText() + s);
JTextField-luokan hierarkia Object-yliluokkaan nähden
	java.lang.Object
  -> java.awt.Component
    -> java.awt.Container
      -> javax.swing.JComponent
        -> javax.swing.JTextComponent
          -> javax.swing.JTextField
Tekstialue - JTextArea
Erona tekstikenttään, tähän komponenttiin voidaan sijoittaa vapaasti useita rivejä tekstiä. Toimii mm. tekstieditorin kenttänä johon teksti syötetään tai ikkunana johon voidaan tulostaa jokin raportti. Teksti alue voidaan sijoittaa scrollPanel-paneelin sisään, jolloin tekstialueen sisältöä voidaan vierittää, jos se ei mahdu näkyvän alueen sisälle.

JTextArea-komponentin muodostimessa annetaan parametreina tekstialueen rivien ja sarakkeiden määrä
textArea = new TextArea(5,30); // 5 riviä ja 30 saraketta
JTextArea-luokan hierarkia Object-yliluokkaan nähden
	java.lang.Object
  -> java.awt.Component
    -> java.awt.Container
      -> javax.swing.JComponent
        -> javax.swing.JTextComponent
          -> javax.swing.JTextArea
Otsikot - JLabel
Erilaisten komponenttien tai lomakkeiden otsikot. Käyttäjä ei pysty editoimalla muuttamaan tekstiä. Tekstin sisällön voi hakea tai sitä voidaan muuttaa getText() ja setText() -metodeilla.

Esimerkki
	Container container = getContentPane();
	container.add(new JLabel("Otsikko"));
JLabel-luokan hierarkia Object-yliluokkaan nähden
	java.lang.Object
  -> java.awt.Component
    -> java.awt.Container
      -> javax.swing.JComponent
        -> javax.swing.JLabel
Valintaruutu - JCheckBox

Jos halutaan vastaus "kyllä" tai "ei", niin kannattaa käyttää valintaruutua. Valintaruutuun kuuluu automaattisesti tehtävän valinnan kertova otsikko, mikä kirjoitetaan muodostimeen. Esim. pieni esimerkki valintapaneelin luomisesta
public MyCheckBoxFrame() {
  JPanel p = new JPanel();
  bold = addCheckBox(p,"Lihavoitu");
  italic = addCheckBox(p,"Kursivoitu");
}

JCheckBox addCheckBox(JPanel p, String name) {
  JCheckBox c = new JCheckBox(name);
  c.addActionListener(this);
  p.add(c);
  return c;
}
JCheckBox-luokan hierarkia Object-yliluokkaan nähden
	java.lang.Object
  -> java.awt.Component
    -> java.awt.Container
      -> javax.swing.JComponent
        -> javax.swing.AbstractButton
          -> javax.swing.JToggleButton
			-> javax.swing.JCheckBox
Valintanappi - JRadioButton
Valinta- tai radionapin käyttö on siinä tapauksessa hyvä jos pitää valita useasta vaihtoehdosta tismalleen yksi. Valintanapit toteutetaan Javassa muodostamalla ensin ButtonGroup komponentti johon voidaan sitten lisätä JRadioButton -komponentteja.

Esim. Lisätään kaksi painiketta painikeryhmään
smallButton = new JRadioButton("Pieni", false);
mediumButton = new JRadioButton("Keskikoko", true);
ButtonGroup group = new ButtonGroup();
group.add(smallButton);
group.add(mediumButton);
JRadioButton-luokan hierarkia Object-yliluokkaan nähden
	java.lang.Object
  -> java.awt.Component
    -> java.awt.Container
      -> javax.swing.JComponent
        -> javax.swing.AbstractButton
          -> javax.swing.JToggleButton
			-> javax.swing.JRadioButton
Luettelot - JList, JComboBox ja JScrollPane Jos pitää valita tietty vaihtoehto lukuisista valinnoista, niin valintanappeja parempia vaihtoehtoja ovat luettelot. JList -komponentti muodostaa luettelon josta voidaan valita tietty alkio. Ja JComboBox -komponentti muodostaa pudotusvalikon, josta voidaan valita tietty alkio.

Esim. Muodostetaan luettelo tekemällä ensin merkkijonotaulukko, joka välitetään muodostimelle parametrina
String[] words = {"1", "2", "3", "4", "5"};
JList wordlist = new JList(words);
JList-luokan hierarkia Object-yliluokkaan nähden
	java.lang.Object
  -> java.awt.Component
    -> java.awt.Container
      -> javax.swing.JComponent
        -> javax.swing.JList
Muodostetaan metodi, joka luo JComboBox -alasvetovalikon
	public JComboBox luoComboBox() {
		String[] lista = {"valinta 1", "valinta 2", "valinta 3", "valinta 4", "valinta 5"};
		JComboBox comboBox = new JComboBox(lista);
		comboBox.setSelectedIndex(0);
		return comboBox;
	}
JComboBox-luokan hierarkia Object-yliluokkaan nähden
	java.lang.Object
  -> java.awt.Component
    -> java.awt.Container
      -> javax.swing.JComponent
        -> javax.swing.JComboBox
JScrollPane-luokalla käyttäen hyväksi JList:iä voi helposti tehdä metodin, joka luo skrollattavan valikon
		public JScrollPane skrollattavaLista() {
		DefaultListModel listModel = new DefaultListModel();
		for (int i = 1; i < 20; i++)
			listModel.addElement("Valinta "+i);
		JList list = new JList(listModel);
		list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		list.setVisibleRowCount(-1);
		list.setSelectedIndex(4);
		JScrollPane listScroller = new JScrollPane(list);
		listScroller.setPreferredSize(new Dimension(250, 80));
		return listScroller;
	}
JScrollPane-luokan hierarkia Object-yliluokkaan nähden
	java.lang.Object
  -> java.awt.Component
    -> java.awt.Container
      -> javax.swing.JComponent
        -> javax.swing.JScrollPane

Swing-komponenttien hierarkia


Lopuksi vielä ohjelmalistaus joka esittelee seuraavat swingin komponentit: JFrame, JPanel, JButton, JToggleButton, JTextField, JPasswordField, JTextArea, JLabel, JList, JScrollPane, JSlider ja JComboBox sekä luokat joita käytetään ikkunan alasvetovalikoiden luomiseen, eli JMenu, JCheckBoxMenu ja JRadioButtonMenu
import javax.swing.*;
import java.awt.*;

public class Components extends JFrame {

	public Components() {
		Container container = getContentPane();
		container.setLayout(new GridLayout(4,4,4,4));
		
		this.setJMenuBar(luoMenu());
			
		container.add(new JButton("OK"));
		container.add(new JToggleButton("On/Off"));
		container.add(new JTextField("JTextField"));
		container.add(new JPasswordField("JPasswordField"));
		container.add(new JTextArea("JTextArea"));
		container.add(new JLabel("JLabel"));
		container.add(skrollattavaLista());	
		container.add(luoSlider('x', 0, 50, 10));
		container.add(luoSlider('y', 0, 20, 0));
		container.add(luoComboBox());
		container.add(luoJPanel());
		
	}
	
	public static void main(String[] args) {
		Components comp = new Components();
		//comp.setSize(800, 600);
		comp.pack();
		comp.setVisible(true);
		comp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);	
	}
	
	public JPanel luoJPanel() {
		JPanel p1 = new JPanel();
		JPanel p2 = new JPanel();
		JPanel p3 = new JPanel();
		JPanel p4 = new JPanel();
		JPanel p5 = new JPanel();
		
		p1.setLayout(new BorderLayout());
		p1.add(p2, BorderLayout.NORTH);
		p1.add(p3, BorderLayout.CENTER);
		
		p2.setLayout(new BorderLayout());
		p2.add(p4, BorderLayout.EAST);
		p2.add(p5, BorderLayout.CENTER);
		
	
		p3.add(skrollattavaLista());
		p3.setBackground(Color.blue);
	
		p4.add(luoComboBox());
		p4.setBackground(Color.green);
		
		p5.add(new JLabel("JLabel"));	
		p5.setBackground(Color.yellow);	
		
		return p1;
	}
	
	public JComboBox luoComboBox() {
		String[] lista = {"valinta 1", "valinta 2", "valinta 3", "valinta 4"};
		JComboBox comboBox = new JComboBox(lista);
		comboBox.setSelectedIndex(0);
		return comboBox;
	}
	
	
	public JSlider luoSlider(char x, int min, int max, int init) {
		JSlider slider;
		if (x == 'x') {
			slider = new JSlider(JSlider.HORIZONTAL, min, max, init);
		}
		else {
			slider = new JSlider(JSlider.VERTICAL, min, max, init);
		}
		slider.setMajorTickSpacing(10);
		slider.setMinorTickSpacing(1);
		slider.setPaintTicks(true);
		slider.setPaintLabels(true);
		return slider;
	}	
	
	public JMenuBar luoMenu() {
		JMenuBar menuBar = new JMenuBar();
		JMenu menu = new JMenu("JMenu menu");
		JMenu submenu = new JMenu("JMenu submenu");
		JMenu anotherSubmenu = new JMenu("JMenu anotherSubmenu");
		JMenuItem item1 = new JMenuItem("JMenuItem item1");
		
		JCheckBoxMenuItem item2 = new JCheckBoxMenuItem("JCheckBoxMenuItem item2");
		JCheckBoxMenuItem item3 = new JCheckBoxMenuItem("JCheckBoxMenuItem item3");
		item3.setSelected(true);
		
		ButtonGroup group = new ButtonGroup();
		JRadioButtonMenuItem item4 = new JRadioButtonMenuItem("JRadioButtonMenuItem item4");
		JRadioButtonMenuItem item5 = new JRadioButtonMenuItem("JRadioButtonMenuItem item5");
		JRadioButtonMenuItem item6 = new JRadioButtonMenuItem("JRadioButtonMenuItem item6");
		item4.setSelected(true);
		group.add(item4);
		group.add(item5);
		group.add(item6);
		
		menuBar.add(menu); 
		menu.add(item1);
		menu.add(submenu);
		submenu.add(item2);
		submenu.add(item3);
		menu.add(anotherSubmenu);
		anotherSubmenu.add(item4);
		anotherSubmenu.add(item5);
		anotherSubmenu.add(item6);
	
		return menuBar;
	}
	
	public JScrollPane skrollattavaLista() {
		DefaultListModel listModel = new DefaultListModel();
		for (int i = 1; i < 20; i++)
			listModel.addElement("Valinta "+i);
		JList list = new JList(listModel);
		list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		list.setVisibleRowCount(-1);
		list.setSelectedIndex(4);
		JScrollPane listScroller = new JScrollPane(list);
		listScroller.setPreferredSize(new Dimension(250, 80));
		return listScroller;
	}
}
Java-koodi on ladattavissa täältä

Piirtäminen Javassa

Paneeliin piirrettäessä täytyy määritellä luokka, joka laajentaa JPanel -luokkaa. Ja syrjäyttää tässä luokassa paintComponent -metodi. PaintComponent-metodi on oikeastaan JComponent eli kantaluokka kaikille swingin osille.

PaintComponent -metodia ei tarvitse kutsua itse, vaan sitä kutsutaan aina automaattisesti esim. ikkunaa suurentaessa. Tätä prosessia ei pitäisi edes häiritä. Kun ikkuna avataan ensimmäisen kerran, sen pitää tietenkin suorittaa lauseet, jotka määräävät miten ikkunan osat piirretään.

Eroja AWT:n:
AWT:ssa piirrettiin Component-luokan aliluokkaan Canvas, joka oli tarkoitettu vain piirtämiseen. Swingissä voidaan piirtää mihin tahansa Swing-komponenttiin.

Enää ei käytetä paint -metodia. Tämän metodin syrjäyttämisen jälkeen ohjelma ei edes toimisi oikein, koska siinä häirittäisiin JComponent.paint -metodia.

Swingin komponentit käyttävät puskurointia poistaakseen välkkymisen.

2D Kuviot
Java.awt.Graphics-pakkauksen metodeilla drawLine, drawArc, drawPolyLine ja drawPolygon piirretään grafiikkaolioon suoria ja käyriä viivoja.

Esim. Helpoin tapa piirtää Javalla monikulmio on luoda monikulmio-olio, lisätä siihen pisteitä ja kutsua drawPolygon -metodia:
Polygon p = new Polygon();
p.addPoint(10,10);
p.addPoint(10,30);
p.addPoint(20,20);
p.drawPolygon(p);
Metodeilla drawRect, drawRoundrect, draw3DRect ja drawOval piirretään suorakulmioita ja soikioita.

Esim. Piirretään ympyrä, jonka vasen yläkulma on pisteessä (0,0). Ympyrä saadaan erikoistapauksena ovaalista asettamalla leveys ja korkeys (kaksi viimeistä parametria) samanpituisiksi.
g.drawOval(0,0,40,40);
Värit
Värin vaihtaminen onnistuu Java.awt.Graphics -luokan metodilla setColor. Kun halutaan piirtää komponentti/kuvio tietyllä värillä, niin ensin valitaan väri jota käytetään piirtokäskyissä.

Esim. Piirretään kaksi eri väristä tekstiä.
g.setColor(Color.blue);
g.drawString("Hello", 70, 100);
g.setColor(Color.green);
g.drawString("World", 75, 125);
Seuraava ohjelmalistaus esittelee kuinka Javalla voidaan piirtää erilaisia neliöitä, ympyröitä, palloja, kaaria ja viivoja
import javax.swing.*;
import java.awt.*;

public class Pic extends JFrame {
	
	public Pic() {	
	
		Container container = getContentPane();
		container.setLayout(new GridLayout(2,2,0,0));
		
		JPanel p1 = new JPanel(new GridLayout(2,2,0,0));
		JPanel p2 = new JPanel(new GridLayout(2,2,0,0));
		JPanel p3 = new JPanel(new GridLayout(2,2,0,0));
		JPanel p4 = new JPanel(new GridLayout(2,2,0,0));	
		


		p1.add(new RectEmpty());
		p1.add(new RectFilled());
		p1.add(new Rect3D());
		p1.add(new Rect3DRaised());

		p2.add(new RectRoundEmpty());
		p2.add(new RectRoundFilled());
		p2.add(new OvalEmpty());
		p2.add(new OvalFilled());
		
		p3.add(new ArcEmpty());
		p3.add(new ArcFilled());
		p3.add(new DrawLine());
		p3.add(new DrawMultipleLine());
		
		p4.add(new RectEmpty());
		p4.add(new RectFilled());
		p4.add(new Rect3D());
		p4.add(new Rect3DRaised());
											
		container.add(p1);
		container.add(p2);
		container.add(p3);
		container.add(p4);			
	}
	
	public static void main(String[] args) {
		Pic gui = new Pic();								
		gui.setSize(450, 450);	
		
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();	
		int screenWidth = screenSize.width;			
		int screenHeight = screenSize.height;
		
		Dimension frameSize = gui.getSize();		
		int x = (screenWidth - frameSize.width)/2;				
		int y = (screenHeight - frameSize.height)/2;	
		
		gui.setTitle("Ikkunan nimi");					
		gui.setLocation(x, y);					
		gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);	
		gui.setVisible(true);						
	}
}

class RectEmpty extends JPanel {
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.red);
		g.drawRect(0, 0, 100, 100);
	}	
	public Dimension getPreferredSize() {
		return new Dimension(100, 100);
	}
}

class RectFilled extends JPanel {
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.green);
		g.fillRect(0, 0, 100, 100);
	}
		public Dimension getPreferredSize() {
		return new Dimension(100, 100);
	}
}

class Rect3D extends JPanel {
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.cyan);
		g.fill3DRect(0, 0, 100, 100, false);
	}
		public Dimension getPreferredSize() {
		return new Dimension(100, 100);
	}
}

class Rect3DRaised extends JPanel {
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.cyan);
		g.fill3DRect(0, 0, 100, 100, true);
	}
		public Dimension getPreferredSize() {
		return new Dimension(100, 100);
	}
}
class RectRoundEmpty extends JPanel {
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.red);
		g.drawRoundRect(0,0,100,100,20,20);
	}
		public Dimension getPreferredSize() {
		return new Dimension(100, 100);
	}
}
class RectRoundFilled extends JPanel {
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.green);
		g.fillRoundRect(0, 0, 100, 100, 20, 20);
	}
		public Dimension getPreferredSize() {
		return new Dimension(100, 100);
	}
}
class OvalEmpty extends JPanel {
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.cyan);
		g.drawOval(0, 0, 100, 100);
	}
		public Dimension getPreferredSize() {
		return new Dimension(100, 100);
	}
}
class ArcFilled extends JPanel {
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.cyan);
		g.fillArc(0, 0, 100, 100, 90, 110);
	}
		public Dimension getPreferredSize() {
		return new Dimension(100, 100);
	}
}
class ArcEmpty extends JPanel {
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.black);
		g.drawArc(0, 0, 100, 100, 270, 180);
	}
		public Dimension getPreferredSize() {
		return new Dimension(100, 100);
	}
}
class DrawLine extends JPanel {
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.black);
		g.drawLine(3, 4, 95, 90);
	}
		public Dimension getPreferredSize() {
		return new Dimension(100, 100);
	}
}
class DrawMultipleLine extends JPanel {
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.black);
		g.drawLine(0, 0, 100, 90);
		g.drawLine(0, 20, 95, 100);
		g.drawLine(13, 14, 85, 90);
		g.drawLine(56, 4, 0, 15);
		g.drawLine(0, 90, 100, 9);
	}
		public Dimension getPreferredSize() {
		return new Dimension(100, 100);
	}
}

Java-koodi on ladattavissa täällä

Layout -managerit

FlowLayout:
Virtaava asettelutapa. Virtaavassa asettelutavassa komponentit sijoitetaan vierekkäin ja kun tila ei enää riitä, niin aloitetaan uusi rivi. Komponenttien koko ei muutu ikkunan kokoa muutettaessa. Tapa millä komponentit sijoitetaan riville voidaan valita joko keskittämällä ne säiliöön tai tasaamalla säiliön vasempaan tai oikeaan reunaan. Tämä on paneelin oletusasettelu.

Esimerkki joka toteuttaa FlowLayoutin
import javax.swing.*;
import java.awt.*;

public class GuiLuokkaFlow extends JFrame {	
	
	public GuiLuokkaFlow() {	
		Container container = getContentPane();							
		container.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 15));
		for (int i = 0; i < 10; i++) 								
			container.add(new JButton("Component " + i));	
	}
	
	public static void main(String[] args) {
		GuiLuokkaFlow gui = new GuiLuokkaFlow();			
		gui.setSize(200, 200);	
		
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		int screenWidth = screenSize.width;			
		int screenHeight = screenSize.height;				
		
		Dimension frameSize = gui.getSize();						
		int x = (screenWidth - frameSize.width)/2;	
		int y = (screenHeight - frameSize.height)/2;
		
		gui.setTitle("Ikkunan nimi");					
		gui.setLocation(x, y);							
		gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		gui.setVisible(true);							
	}
}
Java-koodi ladattavissa täältä

Border Layout:
Reuna-asettelu. Tässä asettelussa voidaan määrätä yksittäisen komponentin sijoittuminen säiliöön, joko keskelle, yläreunaan, alareunaan, vasemmalle tai oikealle.

Esimerkki joka toteuttaa BorderLayoutin
import javax.swing.*;
import java.awt.*;

public class GuiLuokkaBorder extends JFrame {

	public GuiLuokkaBorder() {
		Container container = getContentPane();
		container.setLayout(new BorderLayout(5, 10));
		container.add(new JButton("East"), BorderLayout.EAST);
		container.add(new JButton("South"), BorderLayout.SOUTH);
		container.add(new JButton("West"), BorderLayout.WEST);
		container.add(new JButton("North"), BorderLayout.NORTH);
		container.add(new JButton("Center"), BorderLayout.CENTER);
	}
	
	public static void main(String[] args) {
		GuiLuokkaBorder gui = new GuiLuokkaBorder();
		gui.setTitle("BorderLayout");
		gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		gui.setSize(300,300);
		gui.setVisible(true);
	}
}
Java-koodi ladattavissa täältä

Grid Layout:
Ruudukko-asettelu. Komponentit sijoitetaan ruudukkoon, jossa rivien ja sarakkeiden määrä on ennalta määrätty. Jos ikkunan kokoa muutetaan, niin solujen keskinäiset suhteet säilyvät jolloin komponenttien koko muuttuu.

Esimerkki, joka toteuttaa GridLayoutin
import javax.swing.*;
import java.awt.*;

public class GuiLuokkaGrid extends JFrame {										
	
	public GuiLuokkaGrid() {													
		Container container = getContentPane();									
		container.setLayout(new GridLayout(4, 3, 5, 5));
		for (int i = 0; i < 10; i++) 					
			container.add(new JButton("Component " + i));		
	}
	
	public static void main(String[] args) {
		GuiLuokkaGrid gui = new GuiLuokkaGrid();						
		gui.setSize(200, 200);	
		
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		int screenWidth = screenSize.width;	
		int screenHeight = screenSize.height;
		
		Dimension frameSize = gui.getSize();
		int x = (screenWidth - frameSize.width)/2;
		int y = (screenHeight - frameSize.height)/2;
		
		gui.setTitle("Ikkunan nimi");							
		gui.setLocation(x, y);							
		gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		gui.setVisible(true);											
	}
}
Java-koodi ladattavissa täältä

Box Layout:
Toimii kuten virtaava-asettelu, mutta komponentteja voidaan sijoittaa myös pystysuunnassa, jolloin komponentit pinotaan päällekkäin.

The Grid Bag Layout: Ehkä paras Javan oma asettelumanageri. kuten ruudukko-asettelussa, niin myös tässä komponentit jaetaan ruudukkoihin, mutta solujen ei tarvitse olla keskenään samankokoiset.

Layout-managerit, kuten FlowLayout eivät vaikuta komponenttien koon muuttumiseen ikkunan kokoa vaihdettaessa, koska komponentteja asetellaan sitä mukaa, kun niitä ruudulle mahtuu.

Layout-managerit, kuten GridLayout aiheuttavat komponenttien koon muuttamisen ikkunan kokoa muuttamalla, koska näissä komponenttien määrä riveillä ja sarakkeilla on vakio.

Käyttöliittymä, jossa jotkut komponentit vaihtavat kokoa ja toiset eivät, onnistuu toteuttaa luonnollisesti käyttämällä useita paneeleita, joissa käytetty layout-managereita sen mukaan aiheuttavatko ne komponenttien koon muuttumisen ikkunan kokoa muuttamalla, vai eivät.

Javan tapahtumankäsittely

Javan tapahtumankäsittely toimii karkeasti siten, että tapahtumien lähteisiin (painikkeet, vierityspalkit,..) kohdistuu jokin tapahtuma ja nämä lähteet lähettävät ilmoituksen niille kuuntelijaolioille, jotka on rekisteröity kyseistä tapahtumaa varten. Tapahtuman tieto löytyy tapahtumaoliosta, kaikki nämä oliot on johdettu luokasta Java.util.EventObject. Kuuntelijaoliot päättelevät tapahtumaolion sisällöstä siitä miten tapahtumaan reagoidaan.

AWT:n tapahtumatyypit:
Kuuntelijaolion tulee toteuttaa jokin ???Listener -rajapinta. Rajapinnassa on esitelty ne metodit, mitkä sen toteuttavan luokan tulee sisältää.

AWT:n kuuntelija-rajapinnat:
Esim. ActionListener -rajapinta, johon kuuluu pakollisena actionPerformed -metodi, missä toteutetaan kuuntelijaolion reagointi tapahtuman tiedon perusteella.
public class tapahtumanKuuntelijaOlio implement ActionListener {
  ...
  public void actionPerformed(ActionEvent evt) { ...
Monesti ei tarvita kaikkia metodeja, jotka rajapinta sisältää ja tällöin olisi turhaa kirjoittaa kaikkiin metodeihin sisältö. Javassa tällainen ongelma on kierretty sovitinluokilla. Tällainen luokka on toteutettu AWT:n jokaisesta kuuntelija-rajapinnasta, jossa on enemmän kuin yksi metodi. Sovitinluokassa on yksinkertaisesti jokainen metodi kirjoitettu ilman sisältöä. Laajentamalla sovitinluokkaa voidaan toteuttaa sisältö vaan niille metodeille joita tarvitaan.

Esim. toteutetaan WindowListener -rajapinnasta ainoastaan tapahtuma ikkunan sulkemiselle käyttämällä WindowAdapter -sovitinluokkaa (Core Java 2).
public class Terminator extends WindowAdapter {
  public void windowClosing(WindowEvent e) {
    System.exit(0);
  }
}
Kuuntelijaolio rekisteröidään lähdeolioon seuraavalla lauseella:
tapahtumaLähdeolio.addTapahtumaListener(tapahtumanKuuntelijaOlio);
Tapahtuman aiheuttaja voidaan saada selville kahdella tavalla: Esim. Lisätään paneeliin kaksi painiketta, jotka molemmat ovat tapahtumien lähteitä ja rekisteröidään paneeli kuuntelemaan painikkeiden tapahtumia.
public class ActionListenerPanel extends JPanel implement ActionListener {
  JButton b1;
  JButton b2;

  public ActionListenerPanel() {
    b1 = new JButton("painike1");
    b2 = new JButton("painike2");
    add(b1);
    add(b2);
    b1.addActionListener(this);
    b2.addActionListener(this);
  }

  public void actionPerformed(ActionEvent evt) {
    Object source = evt.getSource();
    String command = evt.getActionCommand();
    if (source == b1)
      System.out.println("Painiketta 1 painettiin);
    else if (command.equals("painike2"))
      System.out.println("Painiketta 2 painettiin);
  }


Viitteet:

[1] Core Java 2 - Horstmann, Cornell