<<< Powrót do przedmiotu Programowanie obiektowe
<<< Powrót do wykładu Graficzny interfejs użytkownika
Zadanie 1
W klasie WitajŚwiecie umieść w oknie głównym drugą etykietę z tekstem. Użyj w tym celu bezparametrowej metody add(). Czemu obie etykiety nie są widoczne?
Podgląd działającego rozwiązania
| Archiwum JAR |
Applet
|
| Żeby uruchomić przykład Po_GUI_Zad1.jar ściągnij najpierw archiwum jar na swój komputer (możesz to zrobić klikając na odnośniku prawym klawiszem myszy i wybierając "Zapisz jako...") i uruchom jak zwykły program. |
<applet code="applet.Zad1Applet" archive="images/d/db/PO_GUI_Applety.jar" width="300" height="120"></applet>
|
Rozwiązanie kod
import javax.swing.*;
public class Zad1 {
private static void utwórzGUI() {
//tworzenie nowego okna
JFrame frame = new JFrame("Okno Zad1");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//dodawanie etykiety z przywitaniem
JLabel label1 = new JLabel("Witaj świecie");
JLabel label2 = new JLabel("Jestem drugą etykietą");
frame.add(label1);
frame.add(label2);
//ustalanie wymiarów i wyświetlanie okna
//frame.pack();
frame.setSize(300,150);
frame.setVisible(true);
}
public static void main(String[] args) {
//aby uniknąć zakleszczeń, tworzenie GUI zawsze zlecamy dla wątku obsługi zdarzeń
SwingUtilities.invokeLater(new Runnable() {
public void run() {
utwórzGUI();
}
});
}
}
Rozwiązanie wyjaśnienie
Widoczna będzie tylko etykieta dodana jako ostatnia, gdyż w każdym rejonie (bezparametrowa metoda add() dodaje komponenty po środku) może znajdować się tylko jeden komponent. Kolejne dodawane komponenty zastępują poprzednie.
Zadanie 2
Zmodyfikuj klasę GridLayoutTest, tak aby to trzecia (tam gdzie jest przycisk P3), a nie szósta pozycja w siatce była pusta.
Podgląd działającego rozwiązania
| Archiwum JAR |
Applet
|
| Żeby uruchomić przykład Po_GUI_Zad2.jar ściągnij najpierw archiwum jar na swój komputer (możesz to zrobić klikając na odnośniku prawym klawiszem myszy i wybierając "Zapisz jako...") i uruchom jak zwykły program. |
<applet code="applet.Zad2Applet" archive="images/d/db/PO_GUI_Applety.jar" width="300" height="120"></applet>
|
Rozwiązanie kod
import java.awt.*;
import javax.swing.*;
public class Zad2 extends JFrame {
Zad2() {
super("Okno Zad2");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridLayout(3,2));
add(new JButton("P1"));
add(new JButton("P2"));
add(new JPanel());//pusty JPanel symuluje puste miejsce
add(new JButton("P3"));
add(new JButton("P4"));
add(new JButton("Bardzo długi przycisk"));
setSize(300,150);
setVisible(true);
}
public static void main(String[] args) {
//aby uniknąć zakleszczeń, tworzenie GUI zawsze zlecamy dla wątku obsługi zdarzeń
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Zad2();
}
});
}
}
Zadanie 3
Wyświetl okno o rozmiarach 300 na 150, zawierające na górze pięć przycisków: P1, P2, P3, P4 i Bardzo długi przycisk rozmieszczonych przez GridLayout o dwóch wierszach i trzech kolumnach, a na dole takie same pięć przycisków rozmieszczonych przy pomocy FlowLayout. Grupy przycisków powinny być rozmieszczone na oknie przez BorderLayout. Sprawdź, czy wszystkie przyciski mieszczą się w oknie o tych rozmiarach.
Podgląd działającego rozwiązania
| Archiwum JAR |
Applet
|
| Żeby uruchomić przykład Po_GUI_Zad3.jar ściągnij najpierw archiwum jar na swój komputer (możesz to zrobić klikając na odnośniku prawym klawiszem myszy i wybierając "Zapisz jako...") i uruchom jak zwykły program. |
<applet code="applet.Zad3Applet" archive="images/d/db/PO_GUI_Applety.jar" width="300" height="120"></applet>
|
Rozwiązanie kod
import java.awt.*;
import javax.swing.*;
public class Zad3 extends JFrame {
JPanel panel1, panel2;
Zad3() {
super("Okno Zad3");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel1 = new JPanel();
panel1.setLayout(new GridLayout(2,3));
panel1.add(new JButton("P1"));
panel1.add(new JButton("P2"));
panel1.add(new JButton("P3"));
panel1.add(new JButton("P4"));
panel1.add(new JButton("Bardzo długi przycisk"));
panel2 = new JPanel();
//Obiekty JPanel domyślnie używają FlowLayout.
panel2.add(new JButton("P1"));
panel2.add(new JButton("P2"));
panel2.add(new JButton("P3"));
panel2.add(new JButton("P4"));
panel2.add(new JButton("Bardzo długi przycisk"));
//Główne kontenery (JApplet, JDialog i JFrame) domyślnie używają BorderLayout.
add(BorderLayout.NORTH, panel1);
add(BorderLayout.SOUTH, panel2);
setSize(300,150);
setVisible(true);
}
public static void main(String[] args) {
//aby uniknąć zakleszczeń, tworzenie GUI zawsze zlecamy dla wątku obsługi zdarzeń
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Zad3();
}
});
}
}
Zadanie 4
Używając BoxLayout i obiektów klasy Box przygotuj program wyświetlający 5 przycisków rozmieszczonych w dwóch kolumnach (w pierwszej trzy w drugiej dwa). Niech w każdej kolumnie przyciski będą wyśrodkowane. Porównaj efekt z przykładem GridLayoutTest.
Podgląd działającego rozwiązania
| Archiwum JAR |
Applet
|
| Żeby uruchomić przykład Po_GUI_Zad4.jar ściągnij najpierw archiwum jar na swój komputer (możesz to zrobić klikając na odnośniku prawym klawiszem myszy i wybierając "Zapisz jako...") i uruchom jak zwykły program. |
<applet code="applet.Zad4Applet" archive="images/d/db/PO_GUI_Applety.jar" width="300" height="120"></applet>
|
Wskazówka 1
Jako pierwszy parametr konstruktora trzeba przekazać obiekt ContentPane, a nie kontener. Obiekt ContentPane dla danego kontenera uzyskuje się przy pomocy metody getContentPane().
Wskazówka 2
BoxLayout respektuje sposób wyśrodkowania preferowany przez komponenty. Do zmiany preferowanego wyśrodkowania komponentu służy metoda setAlignmentX(Component.CENTER_ALIGNMENT).
Rozwiązanie kod
import java.awt.*;
import javax.swing.*;
public class Zad4 extends JFrame {
Box box1, box2;
void dodajPrzycisk(Box box, JButton p) {
//BoxLayout respektuje sposób wyśrodkowania preferowany przez komponenty
p.setAlignmentX(Component.CENTER_ALIGNMENT);
box.add(p);
}
Zad4() {
super("Okno Zad4");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
box1 = new Box(BoxLayout.Y_AXIS);
dodajPrzycisk(box1, new JButton("P1"));
dodajPrzycisk(box1, new JButton("P3"));
dodajPrzycisk(box1, new JButton("Bardzo długi przycisk"));
box2 = new Box(BoxLayout.Y_AXIS);
dodajPrzycisk(box2, new JButton("P2"));
dodajPrzycisk(box2, new JButton("P4"));
//jako pierwszy parametr konstruktora trzeba przekazać obiekt ContentPane, a nie kontener
setLayout(new BoxLayout(this.getContentPane(), BoxLayout.X_AXIS));
add(box1);
add(box2);
setSize(300,150);
setVisible(true);
}
public static void main(String[] args) {
//aby uniknąć zakleszczeń, tworzenie GUI zawsze zlecamy dla wątku obsługi zdarzeń
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Zad4();
}
});
}
}
Zadanie 5
Przygotuj program wyświetlający przycisk, który po najechaniu na niego myszką zmienia położenie. Do zmiany położenia użyj CardLayout.
Podgląd działającego rozwiązania
| Archiwum JAR |
Applet
|
| Żeby uruchomić przykład Po_GUI_Zad5.jar ściągnij najpierw archiwum jar na swój komputer (możesz to zrobić klikając na odnośniku prawym klawiszem myszy i wybierając "Zapisz jako...") i uruchom jak zwykły program. |
<applet code="applet.Zad5Applet" archive="images/d/db/PO_GUI_Applety.jar" width="300" height="120"></applet>
|
Wskazówka 1
Dodaj do przycisków MouseListener, a kod zamieniający kartki umieść w metodzie mouseEntered(MouseEvent)
Wskazówka 2
Jeżeli używasz CardLayout w głównym kontenerze, jako parametr parent metod first(), last(), next() i previous() przekazuj kontener uzyskany z głównego kontenera przy pomocy metody getContentPane(), a nie sam główny kontener.
Rozwiązanie kod
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Zad5 extends JFrame {
Box box1, box2;
JButton p1, p2;
CardLayout karty;
JFrame okno;
//obiekty klasy wewnętrznej mogę korzystać ze składowych obiektu, który je utworzył
class ZamianaKart extends MouseAdapter {
public void mouseEntered(MouseEvent e) {
//jeżeli używasz CardLayout w głównym kontenerze, to metodom oczekującym parametru
//opisanego w dokumentacji jako "the parent container in which to do the layout"
//przekazuj kontener uzyskany z głównego kontenera przy pomocy metody getContentPane(),
//a nie sam główny kontener
karty.next(okno.getContentPane());
}
}
Zad5() {
super("Okno Zad5");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
okno = this;
box1 = new Box(BoxLayout.X_AXIS);
box1.add(Box.createRigidArea(new Dimension(50,0)));
p1 = new JButton("Kliknij");
p1.addMouseListener(new ZamianaKart());
box1.add(p1);
box2 = new Box(BoxLayout.X_AXIS);
box2.add(Box.createRigidArea(new Dimension(170,0)));
p2 = new JButton("Kliknij");
p2.addMouseListener(new ZamianaKart());
box2.add(p2);
karty = new CardLayout();
setLayout(karty);
//okno.setLayout(new GridLayout(2,2));
add(box1, "lewo");
add(box2, "prawo");
setSize(300,150);
setVisible(true);
}
public static void main(String[] args) {
//aby uniknąć zakleszczeń, tworzenie GUI zawsze zlecamy dla wątku obsługi zdarzeń
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Zad5();
}
});
}
}
Zadanie 6
Rozszerz klasę Dodawanie o możliwość zmiany działania na mnożenie. Niech wybór działania będzie możliwy przy pomocy przycisku combo (JComboBox). Niech wynik będzie obliczany zarówno gdy zostanie zaakceptowana wartość z któregoś z pól, oraz gdy zostanie zmienione działanie. Niech zawartość pól tekstowych będzie wyśrodkowana do prawej.
Podgląd działającego rozwiązania
| Archiwum JAR |
Applet
|
| Żeby uruchomić przykład Po_GUI_Zad6.jar ściągnij najpierw archiwum jar na swój komputer (możesz to zrobić klikając na odnośniku prawym klawiszem myszy i wybierając "Zapisz jako...") i uruchom jak zwykły program. |
<applet code="applet.Zad6Applet" archive="images/d/db/PO_GUI_Applety.jar" width="300" height="120"></applet>
|
Rozwiązanie kod
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Zad6 extends JFrame {
JFrame okno = this;
JTextField wynik = new JTextField(9);
JTextField pole1 = new JTextField("1",9);
JTextField pole2 = new JTextField("2",9);
JComboBox działanie = new JComboBox();
public void licz() {
try {
String dz = (String) działanie.getSelectedItem();
Integer w;
if (dz.equals("+"))
w = Integer.parseInt(pole1.getText()) + Integer.parseInt(pole2.getText());
else
w = Integer.parseInt(pole1.getText()) * Integer.parseInt(pole2.getText());
wynik.setText(w.toString());
} catch (NumberFormatException ex) {
wynik.setText("Błąd");
}
}
//do obsługi zdarzeń często używane są anonimowe klasy wewnętrzne
//jeden egzemplarz będzie dzielony przez oba pola
ActionListener sumowanie = new ActionListener() {
public void actionPerformed(ActionEvent ev) {
licz();
}
};
Zad6() {
super("Okno ZliczanieKliknięć");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
panel.add(pole1);
pole1.addActionListener(sumowanie);
pole1.setHorizontalAlignment(JTextField.RIGHT);
działanie.addItem("+");
działanie.addItem("*");
działanie.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
licz();
}
});
panel.add(działanie);
panel.add(pole2);
pole2.addActionListener(sumowanie);
pole2.setHorizontalAlignment(JTextField.RIGHT);
panel.add(new JLabel("="));
wynik.setEditable(false);
panel.add(wynik);
//puste obramowanie odsuwa komponenty od krawędzi
panel.setBorder(BorderFactory.createEmptyBorder(30,15,30,15));
add(panel);
setSize(300,150);
setVisible(true);
}
public static void main(String[] args) {
//aby uniknąć zakleszczeń, tworzenie GUI zawsze zlecamy dla wątku obsługi zdarzeń
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Zad6();
}
});
}
}
Zadanie 7
Komponenty Swing wyświetlające tekst obsługują formatowanie HTML. Korzystając z tego udogodnienia, stwórz prostą aplikację wyświetlającą stronę HTML znajdującą się pod zadanym adresem URL. Do wyświetlania strony użyj obiektu JEditorPane. Do odczytywania strony użyj obiektu java.net.URL.
Podgląd działającego rozwiązania
| Archiwum JAR |
Applet
|
| Żeby uruchomić przykład Po_GUI_Zad7.jar ściągnij najpierw archiwum jar na swój komputer (możesz to zrobić klikając na odnośniku prawym klawiszem myszy i wybierając "Zapisz jako...") i uruchom jak zwykły program. |
<applet code="applet.Zad7Applet" archive="images/d/db/PO_GUI_Applety.jar" width="500" height="380"></applet>
|
Wskazówka
Metoda setPage(URL) nie usuwa wszystkich informacji o poprzednio wyświetlanej stronie, np. definicji stylów.
Aby pozbyć się wszystkich pozostałości należy utworzyć nowy dokument przy pomocy wywołania getEditorKit().createDefaultDocument() i przekazać go do metody setDocument().
Rozwiązanie kod
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Zad7 extends JFrame {
JEditorPane tekst = new JEditorPane();
JTextField adres = new JTextField("http://www.google.pl");
JButton przycisk = new JButton("Wczytaj stronę");
Zad7() {
super("Okno ZliczanieKliknięć");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ActionListener wczytajStronę = new ActionListener() {
public void actionPerformed(ActionEvent ev) {
java.net.URL url = null;
try {
//poprzedni dokument mógł pozostawić style
tekst.setDocument(tekst.getEditorKit().createDefaultDocument());
url = new java.net.URL(adres.getText());
tekst.setPage(url);
} catch (Exception e) {
System.err.println("Błędny URL: " + url);
tekst.setText("Błędny URL: " + url + "\n" + e.getMessage());
}
}
};
adres.addActionListener(wczytajStronę);
przycisk.addActionListener(wczytajStronę);
JScrollPane suwaki = new JScrollPane(tekst);
add(suwaki);
Box box = new Box(BoxLayout.X_AXIS);
box.add(przycisk);
box.add(Box.createHorizontalStrut(10));
box.add(adres);
add(BorderLayout.SOUTH, box);
setSize(500,400);
setVisible(true);
}
public static void main(String[] args) {
//aby uniknąć zakleszczeń, tworzenie GUI zawsze zlecamy dla wątku obsługi zdarzeń
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Zad7();
}
});
}
}