Računalništvo 1 (PRA)

lekcije / Dogodkovno programiranje in Swing

Dogodkovno programiranje in Swing

Swing in AWT (Abstract Widget Toolbox) sta knjižnici, s katerima v Javi programiramo grafične uporabniške vmesnike. Vsebujeta razrede za izdelavo oken, menujev, gumbov, slik, za delo z miško in tipkovnico itn. AWT je osnovna knjižnica, Swing pa je njena nadgradnja.
Kadar uporabljamo Swing in AWT, moramo napisati ustrezni import ukaz:
import java.awt.*;
import javax.swing.*;
Pozor, knjižnica Swing je v sklopu javax.swing.* (dodatna črka x)! V poštev prideju tudi razne podknjižnice, na primer java.awt.event.*.
Naloga 1
[rešitev]
Swing in AWT sta seveda zasnovana v objektnem stilu programiranja. Vsak uporabniški element je objekt. Nekateri objekti so vidni na zaslonu (okno, menu, gumb, slika, besedilo, ...), ostali pa so uporabniku nevidni, v to skupino spadajo t.i. dogodki (event) in razporejevalci (layout manager).
Naštejmo nekaj osnovnih elementov v Swingu:
JFrame
To je samostojno okno. Preprosti programi, kakršne bomo pisali mi, imajo eno samo tako okno. Okno vsebuje ostale elemente, kot je glavni menu, področje za risanje ali vpisovanje besedila, razni gumbi ipd.
JButton
To je gumb, ki prikazuje besedilo ali sliko. Ko ga uporabnik pritisne, se zgodi "dogodek", na katerega lahko program ustrezno reagira.
JLabel
To je področje, ki prikazuje besedilo ali sliko. Uporabnik takega besedila ne more spreminjati.
JTextArea
To je področje za prikazovanje in urejanje besedila.
JFileChooser
To je element, s katerim uporabnik izbere datoteko.
Razred JPanel
To je področje, ki vsebuje ostale elemente, nanj pa lahko tudi rišemo, podobno kot v Applet.
Poleg tega vsebuje Swing še razrede, ki ne predstavljajo grafičnih elementov, ki so vidni uporabniku. Nekateri izmed njih so:
ActionEvent
To je poseben objekt, ki se naredi, kadar pride do "dogodka". Dogodek je na primer pritisk na gumb, pritisk na tipko, premik miške, ipd.
MouseEvent
To je poseben objekt, ki se naredi vsakič, ko uporabnik premakne miško ali pritisne na gumb na miški.
BorderLayout
Okno običajno vsebuje več elementov (gumbe, področja za pisanje, drsnike), ki jih je treba ustrezno razporediti. Razporejanje grafičnih elementov nadzoruje objekt razreda LayoutManager. Takemu objektu pravimo razporejevalnik. Še posebej preprost razporejevalnik je BorderLayout, ki zna v okno razporediti do 5 elementov (na sever, jug, vzhod, zahod in center). Mi bomo uporabili BorderLayout.
GridBagLayout
To je bolj zahteven razporejvalnik, ki zna razporediti elemente v poljubno matriko. GridBagLayout je bolj zapleten za uporabo, zato v tej lekciji ne bomo razlagali, kako se ga uporabi. Kdor bo delal bolj zahtevne uporabniške vmesnike, naj si prebere dokumentacijo sam.
Napišimo preprost program, ki prikazuje rdečo elipso in krog. Uporabnik lahko vtipka polmer kroga, elipsa pa se vedno razteza čez celoten zaslon. Program sestoji iz glavnega okna, slike in nekaterih komponent: krog in elipsa Program sestoji iz treh razredov:
  1. Razred Krog vsebuje glavni program, ki odpre okno.
  2. Razred GlavnoOkno je podrazred JFrame. To je glavno okno, v katero postavimo ostale elemente. Eden od elementov je objekt razreda Slika, ki prikazuje elipso in krog.
  3. Razred Slika je podrazred JPanel in prikazuje sliko.

Glavni program

Glavni program je preprost, ker je njegova edina naloga odpreti glavno okno:
Krog.java
1
2
3
4
5
6
7
8
9
import javax.swing.*;

public class Krog {
    public static void main(String[] args) {
	JFrame okno = new GlavnoOkno();
	okno.pack();
	okno.setVisible(true);
    }
}
V 5. vrstici smo naredili novo okno. S tem se okno še ne prikaže na zaslonu, ampak se naredi samo objekt.
V 6. vrstici pokličemo metodo pack(), ki izračuna razporeditev elementov znotraj okna in njegovo velikost. Okno še vedno ni vidno uporabniku.
V 7. vrstici pokličemo metodo setVisible(true), s katero dejansko aktiviramo okno, da se prikaže na zaslonu.

Okno

Objekt razreda GlavnoOkno vsebuje vsebuje pet elementov: besedilo nad sliko, slika, besedilo "r = " spodaj levo, polje za vnos in gumb.
Elemente naredimo in dodamo v okno v konstruktorju. Element x dodamo s klicem metode getContentPane().add().
Pritisk na gumb se obravnava kot dogodek (ActionEvent), zato mora okno ustrezati vmesniku actionListener().
GlavnoOkno.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import java.awt.*;       // potrebujemo za Dimension
import java.awt.event.*; // potrebujemo za ActionListener
import javax.swing.*;    // potrebujemo za Swing

public class GlavnoOkno extends JFrame implements ActionListener {
    private JTextField besedilo;
    private JLabel naslov;
    private JButton narisiGumb;
    private Slika slika; 
    private Dimension preferredSize = new Dimension(500, 300);

    public GlavnoOkno() {
	getContentPane().setLayout(new BorderLayout());

	slika = new Slika();
	getContentPane().add(slika, BorderLayout.CENTER);

	naslov = new JLabel("Krog");
	getContentPane().add(naslov, BorderLayout.NORTH);

	JPanel p = new JPanel();
	getContentPane().add(p, BorderLayout.SOUTH);

	p.add(new JLabel("r = "));

	besedilo = new JTextField(20);
	p.add(besedilo);

	narisiGumb = new JButton("Narisi");
	p.add(narisiGumb);
	narisiGumb.addActionListener(this);

	// ce uporabnik zapre okno, se program zakljuci
	setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

	// nastavimo naslov okna
	setTitle("Elipsa in krog");
    }

    public Dimension getPreferredSize() {
	return preferredSize;
    }

    public void actionPerformed(ActionEvent e) {
	Object m = e.getSource();;

	if (m == narisiGumb) {
	    try {
		double r = Double.parseDouble(besedilo.getText());
		slika.nastaviPolmer(r);
		naslov.setText("Krog (r = " + r + ")");
	    } catch (NumberFormatException ex) {
		naslov.setText("Krog (neveljaven r)");
	    }
	}
    }
}

Slika

Razred Slika je podrazred JPanel, ki je element podoben razredu Applet. To je splošen grafični element, v katerega lahko rišemo in pišemo tako, da definiramo metodo paintComponent(Graphics g) (v appletu se ta metoda imenuje paint()). Kadar želimo na novo narisati sliko, pokličemo metodo repaint(), kot v 9. vrstici.
Slika.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import javax.swing.*;
import java.awt.*;

public class Slika extends JPanel {
    private double r;

    public void nastaviPolmer(double q) {
	r = q;
	repaint();
    }

    public void paintComponent(Graphics g) {
	int width = getWidth();
	int height = getHeight();

	g.setColor(Color.white);
	g.fillRect(0, 0, width, height);
	g.setColor(Color.red);
	g.fillOval(0, 0, width, height);
	g.setColor(Color.blue);
	g.fillOval(width/2 - (int)r, height/2 - (int)r, 2 * (int)r, 2 * (int)r);
    }
}

Rešitve nalog

Naloga 1

Knjižnica je napisana nad imenom razreda, pri vrhu strani. Razred HtmlWriter je v knjižnici javax.swing.text.html.