W tym wykładzie zostaną omówione kontenery i rozkłady - istotne koncepcje
programowania GUI w Javie. Przedstawimy także najprostsze komponenty Swingu
oraz gotowe komponenty dialogowe.
Dodawanie
do okien
Okna także są kontenerami. W AWT dodajemy komponenty bezpośrednio do okien. W Swingu nie możemy tego robić. Zwykle dodajemy komponenty (w tym kontenery) do contentPane (specjalnego kontenera, stanowiącego standardową zawartość okna). Jeżeli win oznacza okno (np. klasy JFrame), to jego contentPane uzyskamy przez odwołanie: Container cp = win.getContentPane(); i dodawanie komponentu comp wygląda tak: cp.add(comp); // z ew. dodatkowym argumentem a usuwanie tak: cp.remove(comp); |
Najprostsze kontenery – panele (klasy Panel i JPanel) - służą do grupowania elementów.
W Swingu mamy też wyspecjalizowane kontenery (panele dzielone, zakładkowe, przewijane), które mają specjalną konstrukcję i wobec nich używamy innych metod ustalania zawartości.
Panele są umieszczane w innych kontenerach – np. oknach. Domyślnie panele są widoczne, a okna - nie.
Dlatego, uwidocznienie okna (czy dialogu) wymaga użycia metody setVisible(true) lub show() np.
Podstawowe
pojęcia, dotyczące okien
|
okno wtórne (secondary window, child window) = okno które ma właściciela - inne okno okno pierwotne, właściciel innych okien (owner) = okno, które jest właścicielem innych okien Skutki prawa własności:
Okno wtórne może być oknem modalnym lub nie. Modalność oznacza, iż interakcja z oknem pierwotnym jest zablokowana do chwili zamknięcia okna wtórnego. Przy niemodalnym oknie wtórnym - możemy dalej działać na oknie pierwotnym. Z – order = uporządkowanie okien "po osi Z" (czyli jak się okna na siebie nakładają). |
Niektóre metody klasy
Window (dziedziczone przez inne typy okien)
| |
dispose() | usunięcie zasobów graficznych związanych z oknem |
Component getFocusOwner() | zwraca
komponent znajdujący się w oknie, który ma fokus. Okno musi mieć fokus. |
Component getMostRecentFocusOwner() | zwraca komponent znajdujący się w oknie, który otrzyma fokus, gdy okno otrzyma fokus. |
Toolkit getToolkit() | zwraca Toolkit (klasa Toolkit zawiera metody m.in. opisujące graficzne środowisko działania) |
boolean isShowing() | czy jest na ekranie |
void pack() | upakowanie okna zgodnie z preferowanymi rozmiarami komponentów w nim zawartych (rozmiar okna będzie dokładnie taki, by pomieścić zawarte komponenty i nie większy) |
void setCursor(Cursor) | ustal typ kursora nad oknem |
void toBack() | w tło (zmiana Z-order) |
void toFront() | na pierwszy plan (zmiana Z-order) |
void setLocationRelativeTo(Component c) | jeśli c jest null, lub komponent c nie jest widoczny na ekranie, centruje okno w obszarze ekranu. |
Window getOwner() | właściciel okna |
Window[] getOwnedWindows() | tablica okien, których dane okno jest właścicielem |
Niektóre metody klas
Frame/JFrame
| |
Image getIconImage() | jaka ikonka przy minimalizacji? |
MenuBar getMenuBar() | pasek menu (dla Frame) |
JMenuBar getJMenuBar() | pasek menu (dla JFrame) |
String getTitle() | tytul |
boolean isResizable() | czy możliwe zmiany rozmiarów? |
remove(MenuComponent) | usunięcie paska menu |
setIconImage(Image) | jaka ikonka przy minimalizacji? |
setMenuBar(MenuBar) | ustala pasek menu (dla Frame) |
setJMenuBar(JMenuBar) | ustala pasek menu (dla JFrame) |
setResizable(boolean) | ustalenie możliwosci zmiany rozmiarów |
setTitle(String) | zmiana tytułu |
setUndecorated(boolean) | ustala, czy okno ma mieć "dekoracje" (tj. pasek tytułu, ramkę itp.) |
setExtendedState(int stan) | Ustala
stan okna, reprezentowany przez jedną ze stałuch statycznych z klasy Frame (podawane
jako argument - stan): * NORMAL * ICONIFIED * MAXIMIZED_HORIZ * MAXIMIZED_VERT * MAXIMIZED_BOTH Uwaga nie na wszystkich platformach wszystkie w/w stany są możliwe do osiągnięcia. Aby stwierdzić, które tak, a które nie, używamy metody: Toolkit.isFrameStateSupported(int stan) |
class MLabel extends Label { Dimension minSize = new Dimension(100,100); Dimension maxSize = new Dimension(400,400); Dimension prefSize = new Dimension(300,300); MLabel() { super(); } MLabel(String s) { super(s); } public Dimension getMinimumSize() { return minSize; } public Dimension getMaximumSize() { return maxSize; } public Dimension getPreferredSize() { return prefSize; } }
Uwaga: nie wszyscy zarządcy rozkładów biorą te parametry pod uwagę.
Uwaga
Okna Swingu mają złożoną architekturę i nie możemy ingerować w rozkład komponentów okna. Zamiast tego ustalamy zwykle rozkład komponentów contentPane okna np.: JFrame frame = new JFrame(); frame.getContentPane().setLayout(new FlowLayout()); |
Rozkład
|
Właściwości
|
FlowLayout
(rozkład domyślny dla Panel, JPanel) |
FlowLayout() // (center, odstępy 5) FlowLayout(int) // podane wyrówanie FlowLayot(int, int, int) // podane wyrównanie oraz odstępy poziom, pion |
BorderLayout
(układ domyślny dla Frame, Window i Dialog oraz contentPane okien Swingu) |
|
GridLayout
|
GridLayout(n.m) // tablica n x m komponentów, (jeśli n=0 lub m=0, to dany wymiar tablicy zostanie ustalony dynamicznie na podstawie drugiego wymiary i liczby komponentów w kontenerze) GridLayout(n, m, hgap, vgap) // z podanymi odstępami w poziomie i pionie |
import java.awt.*; import javax.swing.*; public class LayShow { public static void main(String[] args) { final int CNUM = 5; // liczba komponentów w panelach String lmNames[] = { "Flow Layout", // opisy rozkładów "Flow (left aligned)", "Border Layout", "Grid Layout(1,num)", "Grid Layout(num, 1)", "Grid Layout(n,m)", }; LayoutManager lm[] = { new FlowLayout(), // rozkłady new FlowLayout(FlowLayout.LEFT), new BorderLayout(), new GridLayout(1,0), new GridLayout(0,1), new GridLayout(2,0), }; // argumenty dla rozkladu BorderLayout String gborders[] = { "West", "North", "East", "South", "Center" }; // Kolory paneli Color colors[] = { new Color(191,225,255), new Color(255,255,200), new Color(201,245,245), new Color(255,255,140), new Color(161,224,224), new Color(255,255,200), }; Icon redDot = new ImageIcon("red.gif"); // ikonka na przycisku JFrame frame = new JFrame("Layouts show"); // okno i contentPane Container cp = frame.getContentPane(); cp.setLayout(new GridLayout(0, 2)); for (int i = 0; i<lmNames.length; i++) { JPanel p = new JPanel(); p.setBackground(colors[i]); // kolor tła panelu p.setBorder(BorderFactory.createTitledBorder(lmNames[i])); // ramka p.setLayout(lm[i]); // ustalenie rozkładu Icon icon = null; // Możemy sprawdzić z jakim rozkładem mamy do czynienia // i odpowiednio do tego coś zrobić (tu: ikonka na przyciskach) if (lm[i] instanceof BorderLayout) icon = redDot; for (int j=0; j < CNUM; j++) { // dodajemy przyciski do paneli JButton b = new JButton("Przycisk "+(j+1), icon); p.add(b, gborders[j]); } cp.add(p); } frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } }
![]() |
Trzy komponenty dodane do pionowego
BoxLayout. Ich maksymalne rozmiary są ograniczone, wolne miejsce pojawia
się u dołu kontenera. Domyślne wyrównanie - do lewej |
![]() |
Zmiana wyrównania komponentów po osi X: setAlignmentX(Component.CENTER_ALIGNMENT) |
![]() |
Pomiędzy komponentami dodano sztywne obszary stworzone metodą Box.createRigidArea(new Dimension(0,10); Wolne miejsce nadal jest lokowane u dołu kontenera, a odstępy między komponentami są stałe |
![]() |
Tym razem pomiędzy komponentami
dodano dwa komponenty-kleje (Box.createGlue()). Przy zmianie rozmiarów kontenera
ew. wolne miejsce jest lokowane pomiędzy komponentami. Jeśli nie ma nadmiarowego
miejsca komponenty stykają się ze sobą. |
![]() |
Tu komponenty nie mają ograniczonych
maksymalnych rozmiarów lub rozmiary te są odpowiednio duże. Wolne miejsce
jest wypełniane przez BoxLayout poprzez zmianę rozmiaru komponentów. Maksymalne
rozmiary komponentów możemy zmieniać dynamicznie za pomocą metody setMaximumSize. |
void chgCont(Component comp) { Container cont = comp.getParent(); // rodzic komponentu // w hierarchii zawierania się komponentów Component[] c = cont.getComponents(); // uzyskanie wszystkich komponentów for (int i=0; i<c.length; i++) { // przyciemnianie i rozjaśnianie Color back = c[i].getBackground(); if (c[i] == comp) c[i].setBackground(back.brighter()); else c[i].setBackground(back.darker()); } LayoutManager lm = cont.getLayout(); if (lm instanceof FlowLayout) { // jeżeli rozkład Flow - dodaj nowy przycisk cont.add(new JButton("Nowy przycisk")); } cont.validate(); // musi być użyte po dodaniu komponentu: // znak, ze kontener ma byc odswieżony }
AWT | SWING |
import
java.awt.*;
... class GuiAWT extends Frame { GuiAWT() { // ustalenie tytułu okna super("Okno aplikacji"); // ustalenie rozkładu; jeśli trzeba np: setLayout(new FlowLayout()); // tworzenie komponentów np. Label lab = new Label("Etykieta"); Button b = new Button("Przycisk"); // Ustalenie własciwości komponentów, // np: lab.setForeground(Color.red); b.setForeground(Color.blue); // Dodanie komponentów do okna np. add(lab); add(b); // ustalenie rozmiarów okna, np.: pack(); // pokazanie okna show(); } public static void main(String[] args) { // w metodzie main tworzymy //obiekt naszej klasy // i wywołujemy konstruktor new GuiAWT(); } } // koniec klasy GuiAWT |
import
java.awt.*;
import javax.swing.*; ... class GuiSwing extends JFrame { // uzyskujemy contentPane okna Container cp = getContenPane(); GuiSwing() { // ustalenie tytułu okna super("Okno aplikacji"); // ustalenie rozkładu; jeśli trzeba np: cp.setLayout(new FlowLayout()); // tworzenie komponentów np. JLabel lab = new JLabel("Etykieta"); JButton b = new JButton("Przycisk"); // Ustalenie własciwości komponentów, // np: lab.setForeground(Color.red); b.setForeground(Color.blue); // Dodanie komponentów do okna np. cp.add(lab); cp.add(b); // ustalenie rozmiarów okna, np.: pack(); // pokazanie okna show(); } public static void main(String[] args) { // w metodzie main tworzymy //obiekt naszej klasy // i wywołujemy konstruktor new GuiSwing(); } } // koniec klasy GuiSwing |
Wszystkie lekkie komponenty Swingu pochodzą od klasy JComponent (będziemy nazywać je J-komponentami).
Dzięki temu:
są komponentami lekkimi o niezależnym od platformy systemowej wyglądzie (ale zależnym od dobieranych przez programistę ustaleń - "Look and Feel")
możemy ustalać czy mają być przezroczyste, czy nie,
istnieje możliwość zewnętrznego ustalania ich preferowanych, maksymalnych i minimalnych rozmiarów (metody setPreferredSize, setMaximumSize, setMinimumSize), oraz ich wyrównania względem innych komponentów (metody setAlignmentX, setAlignmentY)
mogą mieć ramki o dowolnie ustalanej formie,
mogą mieć podpowiedzi ( "dymki" pomocy - fly-over help, tooltips)
mogą być uaktywniane z klawiatury (operowanie na GUI za pomocą klawiatury, nie tylko myszki)
mogą mieć przypisaną dodatkową informację (w postaci tablicy asocjacyjnej, kojarzącej obiekty-klucze i obiekty-wartości)
Teraz omówimy tylko ramki, przezroczystość i podpowiedzi, inne właściwości (akcje klawiaturowe i tablice asocjacyjne) zostaną przedstawione w kolejnych wykładach.
Typ ramki
|
Znaczenie
|
Uwagi
|
empty | obszar pusty | obramowanie (odstęp) |
line | ramka liniowa | może być ustalony kolor linii |
titled | ramka z tytułem (napisem) | położenie tytułu może być konfigurowane, dodatkowo można podać ramkę innego typu, do której dodawany jest tytuł |
etched | ramka akwafortowa | może być koloryzowana |
bevel | ramka skośna (brzegi 3D) | może być wypukła (raised) albo wklęsła (lowered); może być koloryzowana |
softbevel | j.w. z wygładzonymi brzegami | dostępna poprzez klasę SoftBevel; BorderFactory jej nie dostarcza |
matte | ramka matowa (od matowości w fotografii) | matowość znaczy: dobieranie kolorowych brzegów o dowolnych (np. różnych z prawej i lewej strony) rozmiarach lub wypełnianie ikoną |
compound | ramka złożona | dowolna kombinacja dwóch dowolnych ramek (w tym: ramek złożonych). |
Oto przepis.
np. ramka liniowa w kolorze niebieskim:
comp.setBorder(BorderFactory.createLineBorder(Color.blue)
Ciekawym rozwiązaniem są ramki złożone, powstające z nałożenia na siebie dwóch ramek.
Możemy przy tym wykorzystać już istniejącą ramkę dowolnego J-komponentu.
Np. dodanie ramki liniowej w kolorze niebieskim do już istniejącej ramki komponentu comp wygląda tak:
comp.setBorder( BorderFactory.createCompoundBorder( BorderFactory.createLineBorder(Color.blue), comp.getBorder());
Ale na tym nie koniec: twórcom Swingu przyświecała idea (jeszcze większej) otwartości.
Nic zatem nie stoi na przeszkodzie, by zbudować całkiem własną, całkiem oryginalną ramkę okalającą dowolny J-komponent.
Aby to zrobić, należy:
import javax.swing.border.*; //... private Border empty = BorderFactory.createEmptyBorder(), blackLine = BorderFactory.createLineBorder(Color.black), redLine = BorderFactory.createLineBorder(Color.red), titled1 = BorderFactory.createTitledBorder("Tytuł"), titled2 = BorderFactory.createTitledBorder(redLine,"Tytuł"), etched = BorderFactory.createEtchedBorder(), etchedC = BorderFactory.createEtchedBorder(Color.red, Color.yellow), raisedBevel = BorderFactory.createRaisedBevelBorder(), loweredBevel = BorderFactory.createLoweredBevelBorder(), matteColor = BorderFactory.createMatteBorder(5, 10, 5, 15, Color.blue), matteIcon = BorderFactory.createMatteBorder(24,24,24,24, new ImageIcon("Volume24.gif")), softBevR = new SoftBevelBorder(SoftBevelBorder.RAISED), softBevL = new SoftBevelBorder(SoftBevelBorder.LOWERED), compound1 = BorderFactory.createCompoundBorder(softBevR, softBevL), compound2 = BorderFactory.createCompoundBorder(redLine, compound1), compound3 = BorderFactory.createCompoundBorder( BorderFactory.createLineBorder(Color.blue), matteIcon);
int getIconWidth() int getIconHeigh() void paintIcon(Component c, int x, int y)
JFrame f = new JFrame(...); ... Jlabel l = new JLabel(new ImageIcon("Obraz.jpg")); f.getContentPane.add(l);Warto pamiętać, że ikony mają zadane rozmiary: obraz z pliku jest wyświetlany w oryginalnych rozmiarach. Jeśli chcemy je zmienić, to musimy pobrać obraz "z ikony" (metoda getImage() z klasy ImageIcon) i go reskalować metodami klasy Image lub poprzez drawImage(...) z klasy Graphics.
Etykiety są komponentami opisowymi o następujących właściwościach:
możliwe jest umieszczania ikon obok (lub zamiast) tekstu etykiety (tekst lub ikonę podajemy jako argument konstruktora, możemy je też pobrać za pomoca metod getText() i getIcon() oraz ustalić za pomocą metod setText(String), setIcon(Icon),
możliwe jest kontrolowanie położenia ikony i/lub tekstu w obszarze etykiety w pionie i poziomie (metody setHorizontalAlignment(int), setVerticalAlignment(int))
mozliwe jest kontrolowanie położenia tekstu wobec ikony (setHorizontalTextPosition(int), setVerticalTextPosition(int))
możliwe jest wyświetlanie tekstów HTML na etykiecie (dzięki czemu, na przykład, można w prosty sposób zrealizować wielowierszowe etykiety z fragmentami tekstu w różnych stylach),
z każdą etykietę za pomocą metody labelFor(Component) można skojarzyć komponent ("oznaczany" przez tę etykietę). Jeśli dodatkowo ustalimy skrót klawiaturowy za pomocą metody setDisplayedMnemonic(char), to podany znak będzie w etykiecie podkreślony, a naciśnięcie klawiszy alt-znak spowoduje przejście fokusu do komponentu oznaczanego przez etykietę.
import java.awt.*; import javax.swing.*; class Labels extends JFrame implements SwingConstants { final Color RED = Color.red, BLUE = Color.blue, YELLOW = Color.yellow, WHITE = Color.white, BLACK = Color.black; public Labels() { Container cp = getContentPane(); cp.setLayout(new GridLayout(0,2)); Icon i = new ImageIcon("red.gif"); cp.add(creLab("Lab 1",i, BLACK, YELLOW, LEFT, TOP, LEFT, CENTER)); cp.add(creLab("Lab 2",i, WHITE, BLUE, CENTER, CENTER, CENTER, BOTTOM)); cp.add(creLab("Lab 3",i, RED, WHITE, RIGHT, BOTTOM, RIGHT, CENTER)); cp.add(creLab("Lab 4",i, YELLOW, BLACK, LEFT, CENTER, CENTER, TOP)); setDefaultCloseOperation(EXIT_ON_CLOSE); pack(); show(); } JLabel creLab(String txt, Icon icon, Color fc, Color bc, int halign, int valign, int htxtpos, int vtxtpos) { JLabel l = new JLabel(txt); l.setFont(new Font("Dialog", Font.BOLD, 24)); l.setOpaque(true); l.setIcon(icon); l.setBackground(bc); l.setForeground(fc); l.setHorizontalAlignment(halign); l.setVerticalAlignment(valign); l.setHorizontalTextPosition(htxtpos); l.setVerticalTextPosition(vtxtpos); return l; } public static void main(String args[]) { new Labels(); } }pokaże na ekranie różne formy pozycjonowania napisów wobec ikon w ramach etykiet:
import java.awt.*; import javax.swing.*; import java.util.*; import java.io.*; class Labels2 extends JFrame { Container cp = getContentPane(); JPanel panel = new JPanel(new GridLayout(0,2)); Labels2() { String html = "<html><center>Proszę<br>"+ "<b><font color=red>wpisywać</font></b><br>" + "<font color=blue>swoje <b>prywatne</b> dane" + "</font></center></html>"; JLabel head = new JLabel(html); head.setHorizontalAlignment(JLabel.CENTER); cp.add(head, BorderLayout.NORTH); addLabAndTxtFld("Nazwisko", 'n'); addLabAndTxtFld("Rok urodzenia", 'r'); addLabAndTxtFld("Adres", 'a'); cp.add(panel); cp.setBackground(Color.yellow); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pack(); show(); } void addLabAndTxtFld(String txt, char mnemonic) { JLabel l = new JLabel(txt); l.setHorizontalAlignment(JLabel.RIGHT); JTextField tf = new JTextField(30); l.setLabelFor(tf); l.setDisplayedMnemonic(mnemonic); panel.add(l); panel.add(tf); } public static void main(String args[]) { new Labels2(); } }
Przy czym prawie wszystkie
metody do operowania na przyciskach
znajdują się w klasie
AbstractButton.
import javax.swing.*; import java.awt.*; import java.awt.event.*; class IconA implements Icon { Color color; int w = 40; boolean frame; IconA(Color c, boolean frame) { color = c; this.frame = frame; } public void paintIcon(Component c, Graphics g, int x, int y) { g.setColor(color); w = ((JComponent) c).getHeight()/2; int p = w/4, d = w/2; g.fillOval(x+p,y+p, d, d); if (frame) g.drawRect(x,y,w-1,w-1); } public int getIconWidth() { return w; } public int getIconHeight() { return w; } } class Butt1 implements SwingConstants { JFrame f = new JFrame(); JComponent cp = (JComponent) f.getContentPane(); Icon[] icons = { new IconA(Color.yellow, false), // normal new IconA(Color.blue, false), // over new IconA(Color.red, true), // pressed new IconA(Color.black, false), // selected }; Butt1() { cp.setLayout(new GridLayout(0, 1, 10, 10)); JButton b = new JButton("Button"); setButt(b, icons, RIGHT, CENTER); JButton bmov = new JButton("Button - mouse over"), bpre = new JButton("Button - pressed"); setButt(bmov, icons, LEFT, TOP); setButt(bpre, icons, CENTER, TOP); JToggleButton tb = new JToggleButton("ToggleButton - selected"); setButt(tb, icons, CENTER, BOTTOM); f.pack(); f.show(); bpre.doClick(5000); } void setButt(AbstractButton b, Icon[] i, int horPos, int vertPos) { b.setFocusPainted(false); b.setIcon(i[0]); b.setRolloverIcon(i[1]); b.setPressedIcon(i[2]); b.setSelectedIcon(i[3]); b.setHorizontalTextPosition(horPos); b.setVerticalTextPosition(vertPos); cp.add(b); } public static void main(String args[]) { new Butt1(); } }
JMenuBar | pasek menu, dodawany do okna ramowego JFrame lub JInternalFrame lub do apletu (JAplet) |
JSeparator | Komponent służący do rozdzielania menus na pasku lub elementów (opcji) menu |
JMenu | Menu rozwijalne. Zawiera elementy, z których każdy może być też menu rozwijalnym. |
JPopupMenu | Menu kontekstowe (o nim w następnych wykładach) |
JMenuItem | Element menu (opcja) |
JCheckBoxMenuItem | Element menu – znacznik (zaznaczony-nie) |
JRadioButtonMenuItem | Element menu – radio-przycisk (tylko jeden w danej grupie może być zaznaczony; do grupowania służy omówiona wcześniej klasa ButtonGroup) |
Procedura tworzenia menu rozwijalnego
|
|
1. Utworzyć jedno lub więcej menu rozwijalne |
JMenu m = new JMenu("NazwaMenu"); |
2. Tworzyć elementy i dodawać je do menu m |
JMenuItem mi = new JMenuItem("NazwaOpcji"); m.add(mi); |
3. Jeśli chcemy mieć kolejny poziom, to:
|
JMenu m2 = new JMenu("NazwaM2"); JMenuItem mmi = new JMenuItem(...) m2.add(mmi); m.add(m2); |
4. Stworzyć pasek menu i dodać do niego wszystkie menus 1-go poziomu |
JMenuBar mb = new JMenuBar(); mb.add(m); |
5. Dla danego okna ramowego ustalić pasek menu |
JFrame f ... ; f.setJMenuBar(mb); |
JMenuItem mi(String t, Icon i, int mnemo, String accel) { JMenuItem mi = new JMenuItem(t, i); // element menu z tekstem t oraz ikoną i mi.setMnemonic(mnemo); // ustalenie mnemoniki mi.setAccelerator(KeyStroke.getKeyStroke(accel)); // ustalenie akceleratora return mi; }Aby stworzyć menu rozwijalne "File" stosujemy następujący kod, wykorzystujący pokazaną metodę mi:
JMenu menu = new JMenu("File"); JMenuItem mi = mi("New", newIcon, 'n', "control N"); menu.add(mi); // dodanie opcji do menu menu.add(mi("Open", openIcon, 'o', "control O" )); menu.addSeparator(); // dodaje separator menu.add(mi("Exit", null, 'x', "control X"));Zmienne oznaczające ikony wskazują tu na odpowiednie obiekty klasy ImageIcon (wczytany obrazek GIF lub JPEG).
JMenu menu1 = new JMenu("Run"); menu1.setIcon( new ImageIcon("red.gif")); menu1.setMnemonic('r'); menu1.setHorizontalTextPosition(SwingConstants.LEFT);
JMenuBar mb = new JMenuBar(); mb.add(menu); // menu "File" mb.add(menu1); // menu "Run" f.setJMenuBar(mb); // f - oznacza obiekt typu JFrameAle cóż to jest "menu-bar"? Pasek menu (klasa JMenuBar), który jest J- komponentem, a więc i kontenerem (!). Domyślny rozkład w tym kontenerze - to BoxLayout (horizontal). Oczywiście, możemy go zmienić (ciekawe efekty).
JSeparator sep = new JSeparator(SwingConstants.VERTICAL); sep.setMaximumSize(new Dimension(100,100)); mb.add(sep); JMenu menu2 = new JMenu("View"); menu2.setIcon(new ImageIcon("green.gif")); mb.add(menu2); mb.add(Box.createHorizontalGlue()); JMenu menu3 = new JMenu("Help"); mb.add(menu);
String msg = "<html><center><b>Proszę<br>"+ "<font color=blue>WYŁĄCZYĆ KOMPUTER</font><br>" + "bo się<font color=red> przegrzał</font></b></center></html>"; ImageIcon ikona = new ImageIcon("monitor.jpg"); JOptionPane.showMessageDialog(null, // okno-własciciel msg, // komunikat "Uwaga! uwaga!", // tytuł JOptionPane.WARNING_MESSAGE, // rodzaj komnunikatu ikona // ikona );
String val = "", msg = "Podaj dwie liczby całkowite"; while ((val = JOptionPane.showInputDialog(msg, val)) != null) { StringTokenizer st = new StringTokenizer(val); boolean error = false; if (st.countTokens() != 2) error = true; try { int a = Integer.parseInt(st.nextToken()); int b = Integer.parseInt(st.nextToken()); } catch (Exception exc) { error = true; } if (error) msg = "<html>Wadliwe dane. " + "Podaj <font color=red>DWIE liczby CAŁKOWITE</font></html>"; else break; }
String[] mozliwosci = { "Polska", "Czechy", "Hiszpania", "Tunezja" }; String ans = (String) JOptionPane.showInputDialog( null, // okno-rodzic null, // komunikat "Wybierz kraj", // tytuł JOptionPane.QUESTION_MESSAGE, // typ komunikatu new ImageIcon("cross.gif"), // ikona mozliwosci, // mozliwosci do wyboru mozliwosci[0] // inicjalnie wybrana );
String[] opcje = { "Przywróć", "Zapisz", "Kompiluj"}; int rc = JOptionPane.showOptionDialog( null, // okno "Co mam zrobić?", // komunikat "Program zmodyfikowany", // tytuł JOptionPane.DEFAULT_OPTION, // rodzaj przycisków u dołu (tu nieważny) JOptionPane.QUESTION_MESSAGE,// typ komunikatu (standardowa ikona) null, // własna ikona (tu: brak) opcje, // własne opcje - przyciski opcje[1]); // domyślny przycisk System.out.println("Wybrałeś " + rc + " " + opcje[rc]);
JTextArea list = new JTextArea(10,20); // edytor list.setBorder(BorderFactory.createLineBorder(Color.blue)); JTextField adres = new JTextField(10); // pole tekstowe // tablica opcji Object[] opcje = { new JLabel("Adres"), // etykieta adres, // pole tekstowe "Wyślij" // z "Wyślij" powstanie przycisk }; int rc = JOptionPane.showOptionDialog( null, list, // komunikatem może być dowolny obiekt! "Treść listu", // tytuł JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, opcje, // opcje - to też dowolne obiekty! opcje[2] // domyślnie - przycisk "Wyślij" ); if (rc == 2) { String tekstListu = list.getText(); String adr = adres.getText(); System.out.println("wysyłam na adres " + adr + " :"); System.out.println(tekstListu); }
String choiceMsg(String title, // tytuł String[] normalMsg, // normalne wiersze komunikatów String[] radioMsg, // radio-przyciski (opcje do wyboru) Icon icon // ikona ) // metoda zwraca tekst wybranego radio-przycisku { Object[] msg = new Object[normalMsg.length + radioMsg.length]; for (int i = 0; i < normalMsg.length; i++) msg[i] = normalMsg[i]; JRadioButton rb[] = new JRadioButton[radioMsg.length]; ButtonGroup bg = new ButtonGroup(); for (int i = 0; i < radioMsg.length; i++) { rb[i] = new JRadioButton(radioMsg[i]); bg.add(rb[i]); msg[normalMsg.length +i] = rb[i]; } JOptionPane.showMessageDialog(null, msg, title, 0, icon); for (int i =0; i < rb.length; i++) if (rb[i].isSelected()) return rb[i].getText(); return null; } // ... poniższy fragment pokazuje wywołanie metody choiceMsg String s = choiceMsg( "Wyjazd nad morze", new String[] { "Wybierz środek transportu,", "zaznaczając jedną z opcji", " " }, new String[] { "Autokar", "Pociąg", "Samolot" }, new ImageIcon("bview2.jpg") ); System.out.println("Wybrałeś: " + s);
String[] opcje = { "Otwarcie pliku", "Zapis pliku", "Wybór koloru" }; JLabel msgLabel = new JLabel("Wybierz dialog"); // etykieta dialogu msgLabel.setHorizontalAlignment(JLabel.CENTER); msgLabel.setOpaque(true); msgLabel.setBackground(Color.yellow); msgLabel.setBorder(BorderFactory.createLineBorder(Color.red)); JFileChooser fc = new JFileChooser(new File(".")); // dialog plikowy // z bieżącym katalogiem String approveButt = ""; // tekst na przycisku dialogu plikowego int rc = 0; while (rc != -1) { rc = JOptionPane.showOptionDialog(null, msgLabel, "Test chooserów", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, opcje, opcje[0] ); switch (rc) { case 0 : case 1 : approveButt = opcje[rc]; int retVal = fc.showDialog(null, approveButt); if (retVal == JFileChooser.APPROVE_OPTION) System.out.println(approveButt + " " + fc.getSelectedFile()); break; case 2 : Color nc = JColorChooser.showDialog(null, "Wybierz kolor", msgLabel.getBackground() // inicjalny kolor ); if (nc != null) { System.out.println("Wybrany kolor: " + nc); msgLabel.setBackground(nc); // zmiana koloru etykiety } break; default: break; } }Dialog opcyjny tworzony przez ten program daje możliwość wyboru rodzaju dialogu:
Pięć przycisków z napisami "Przycisk 1" - "Przycisk 5" pokazać w oknie:
a) w układzie BorderLayou
b) w układzie FlowLayout
c) w układzie FlowLayout z wyrównaniem do lewej
d) w układzie FlowLayout z wyrównaniem do prawej
e) w układzie GridLayout jako jeden wiersz
f) jako jedną kolumnę
g) jako tablice (3, 2)
Proszę napisać to jako jedną aplikację, w której sposób układania komponentów
określany jest w dialogu wejściowym poprzez podanie odpowiedniej
litery (A-G).
Pokazuje to rysunek:
- txt - tekst etykiety lub napis null
- icon - nazwa pliku z ikoną etykietu lub napis null
- border - czy ma ramkę (0 lub 1) - typ ramki - do wyboru
- minsize, maxsize, prefsize - minimalne, maksymalne i prefreowane rozmiary (pary liczb)
- align - wyrównanie - (napisy LEFT, RIGHT, CENTER)