Grafiska användargränssnitt i Java – 2015

advertisement
Grafiska användargränssnitt
i Java
jonas.kvarnstrom@liu.se – 2015
Komponenter:
Fönster, knappar, menyer,
färgväljare och
andra grafiska element
som syns på skärmen
(components)
Behållare:
De komponenter som
innehåller andra
komponenter –
till exempel fönster
(containers)
SwingSet3:
finns på nätet
2
jonkv@ida
Terminologi
3
Java Foundation Classes (JFC)
AWT:
Abstract Window Toolkit
Swing
Java 2D
Koppling till OS
Layout
Händelsehantering
Enkla komponenter
Uppdaterade och mer
avancerade GUIkomponenter
2D-grafik
(linjer, rektanglar, kurvor,
färger, mönster, …)
Komponenter: Frame,
Button, List, TextField, …
Komponenter: JFrame,
JButton, JList, JTextField,
…
Använd inte – föråldrade!
Använd dessa!
jonkv@ida
Java Foundation Classes
Steg 1 (idag):
Att använda färdiga komponenter: Knappar, menyer, …
Layout
Händelsehantering – ”någon tryckte en knapp"
Steg 2 (nästa gång):
Att rita på skärmen
Att skapa egna komponenter

Mål: En väldigt enkel ”ordbehandlare” (texteditor)
6
jonkv@ida
Genomgående exempel

Ett vanligt fönster: JFrame
▪ public class WordProcessor {
private JFrame frame;
8
http://docs.oracle.com/javase/tutorial/
uiswing/components/frame.html
Ordbehandlaren behöver
”komma ihåg” sitt fönster
public WordProcessor() {
this.frame = new JFrame("Word Processor 1.0");
frame.setSize(640, 300);
Sätt fönsterstorleken,
frame.setVisible(true);
se till att fönstret visas på skärmen
}
public static void main(String[] args) {
new WordProcessor();
}
}
Skapa ett objekt, glöm bort det, och sedan är vi klara?
Så länge det finns ett öppet fönster, avslutas inte Java!
Vi kan fortfarande använda fönstret genom GUI-händelser (events)
 Ta reda på skärmens storlek:
▪ frame.getToolKit().getScreenSize()
jonkv@ida
Att öppna ett fönster

10
En JFrame är en behållare (container)
http://docs.oracle.com/javase/tutorial/
uiswing/components/frame.html
 Komponent som kan innehålla andra komponenter
 Kan även innehålla andra behållare
Fönstertitel

Menyrad
Kan läggas till vid behov
Innehåll:
Content pane
Hela fönstrets innehåll.
utom titelrad / menyrad
jonkv@ida
Behållare 1: JFrame

11
jonkv@ida
Behållare 2: Innehållshierarki
Skapar en hierarki av innehåll
 Varje behållare har en lista med barn
Fönster
Menyrad
Meny: File
Val1
Val2
Meny: Edit
Val3
ContentPane
Meny: Help
Knapp1
Knapp2
Textfält
Har inget att göra med
arvshierarkin!
Statusrad
12
jonkv@ida
Knappar i Java
http://docs.oracle.com/javase/tutorial/
uiswing/components/button.html
http://docs.oracle.com/javase/tutorial/
uiswing/components/buttongroup.html
Stödklasser
Grunden för
Swing-komponenter
Gemensam implementation: Knappar
Har två lägen, av/på
Radioknappar: Bara
en aktiv åt gången i
varje ButtonGroup
Standardknapp
Checkbox, av/på
13
http://docs.oracle.com/javase/tutorial/
uiswing/components/text.html
Abstrakt, gemensam funktionalitet
Editera text med flera
stilar: HTML, …
En enda rad text
Textarea med
flera rader
Speciell formattering för
datum, valuta, …
Lösenord syns inte
när de skrivs in
jonkv@ida
Textkomponenter

14
http://docs.oracle.com/javase/tutorial/
uiswing/components/label.html
För att lägga till komponenter:
▪ public WordProcessor() {
this.frame = new JFrame("Word Processor 1.0");
frame.add(new JButton("B"));
frame.add(new JButton("I"));
frame.add(new JButton(“U”));
frame.add(new JButton(“Left"));
frame.add(new JButton(“Center"));
frame.add(new JButton(“Right"));
Lägger till flera komponenter
till behållaren – fönstret
Inget syns på skärmen än!
frame.add(new JTextPane());
frame.add(new JLabel("Status: OK")); // Visar text, kan inte editeras
frame.pack();
frame.setVisible(true);
}
NU är det dags att visa
fönstret och dess innehåll
jonkv@ida
Ordbehandlare med komponenter

15
Resultat:
 Rätt komponenter
Liten textarea
 Fel layout
JFrame
Content Pane
JButton
JButton
JButton
JButton
JButton
JTe
xtP
ane
JLabel
jonkv@ida
Resultat

17
Önskad layout (positioner och storlek):
JFrame
Content Pane
JButton
JTextPane
JLabel
JButton
JButton
JButton
JButton
jonkv@ida
Önskad layout

18
Hur ska behållarens komponenter få rätt position och storlek?
 Enklast: Absoluta koordinater
▪ component.setSize(int width, int height);
▪ component.setLocation(int x, int y); // Relativt behållarens övre vänstra hörn
 Fördelar / nackdelar:
▪ (+) Enkelt att förstå
▪ (+) Enkelt att skriva GUI-designer
▪ (–) Inget stöd för att ändra storlek
(Gammaldags Windows-dialoger
har alltid en fast storlek…)
▪ (–) Hur hanterar man större text?
▪ (–) Hur hanterar man översättningar
till andra språk,
där ord kan ta mer plats?
jonkv@ida
Layout 1: Absoluta koordinater?

Preferred Size
19
http://docs.oracle.com/javase/tutorial/
uiswing/layout/index.html
Komponenter kan tala om sin önskade storlek (preferred size)
JButton: Storlek på texten i inställd fontstorlek + lite marginaler
Ingen text
inskriven 
preferred size
är minimal!
Varje behållare har en layouthanterare (layout manager)
Frågar subkomponenter hur stora de vill vara
Applicerar layoutregler (här: "Allt i en rad")
Summerar, beräknar behållarens önskade storlek
jonkv@ida
Layout 2: Önskad storlek
20
jonkv@ida
Layout 3: Innehållshierarkin
Anropa pack() i ett fönster (frame)…
…Så frågar den sin layouthanterare hur mycket plats den behöver
 använd den storleken!
Fönster
Menyrad
Meny: File
Val1
Val2
Meny: Edit
Val3
ContentPane
Meny: Help
Knapp1
Knapp2
Textfält
Statusrad
21
När en komponent får större storlek än den begärda:
Layouthanteraren har regler för hur utrymmet ska användas
Extra utrymme på höjden:
Ska användas till textarean
Extra utrymme på bredden:
Menyrad: Extra plats mellan Edit och Help
Knapprad: Allt vänsterjusterat
Textfält, statusrad: Använder hela utrymmet
Just nu:
jonkv@ida
Layout 4: Annan storlek än önskad
När en komponent får mindre storlek än den begärda:
Layouthanteraren har regler för hur komponenter placeras, (krymps)
Just nu:
22
jonkv@ida
Layout 5: Annan storlek än önskad
23
Flera enkla layouthanterare är inbyggda
Save changes before exiting?
Yes
No
Cancel
Hur kan man skapa en mer
komplex layout med dessa?
jonkv@ida
Layouthanterare 1: ”Inbyggda”

24
JFrame
Använd hierarkin!
 Lägg till en panel
så att alla knappar
är i en egen
”grupp”
 JPanel
jonkv@ida
Layouthanterare 2: Hierarkisk layout
JMenu
JMenu
JMenuBar
JMenu
Content Pane
JButton
JButton
JButton
JButton
JButton
JPanel
JTextPane
JLabel
Fönster
Menyrad
Meny1
Val1
Val2
ContentPane
Panel
Meny2
Val3
Knapp1
Knapp2
Textfält
Statusrad

MigLayout – rekommenderas starkt!
 Baseras på flexibelt rutnät, modern, extremt flexibel
▪ this.setLayout(new MigLayout());
this.add(firstNameLabel);
this.add(firstNameTextField);
this.add(lastNameLabel,
"gap unrelated");
this.add(lastNameTextField, "wrap");
this.add(addressLabel);
this.add(addressTextField,
…
25
Default:
Använder preferred size;
fortsätter på samma rad;
lägger till ett mellanrum
som passar relaterade
komponenter
Mellanrum för två
orelaterade komponenter
Ny rad efter den här
komponentent
"span 3, grow");
Spänn över 3 kolumner,
låt textfältet växa större
än sin önskade storlek
Layoutparametrar för
varje komponent
http://www.miglayout.com/QuickStart.pdf
http://www.migcalendar.com/miglayout/mavensite/docs/cheatsheet.html
jonkv@ida
Layouthanterare 3: MigLayout

Kodskelett:
▪ public class WordProcessor {
private JTextPane text; // References to some components
private JLabel status;
// that we will have to access at various times
private JFrame frame;
public WordProcessor() {
this.frame = new JFrame("Word Processor 1.0");
createGUI();
// Adds components to the frame
createMenus();
// Adds menus
frame.pack();
// Adapt window size
frame.setVisible(true); // Show the window!
}
public static void main(String[] args) {
new WordProcessor();
}
}
26
jonkv@ida
Ordbehandlaren 1: Ett skelett

27
Knappar ligger i sin egen panel
 Inte ett krav med MigLayout!
 Men låter oss ta bort och lägga till knappar utan att påverka resten:
Huvudfönstrets layouthanterare ser alltid “en panel”
▪ private JPanel createButtonPanel() {
final JPanel buttons = new JPanel();
buttons.setLayout(new MigLayout());
buttons.add(new JButton("B"));
buttons.add(new JButton("I"));
buttons.add(new JButton("U"));
buttons.add(new JButton("Left"), “gapleft 10pt”);
buttons.add(new JButton("Center"));
buttons.add(new JButton("Right"));
}
buttons.add(new JButton("Print"), “gapleft 10pt”);
return buttons;
Separation
10 punkters marginal till
vänster om komponenten
jonkv@ida
Ordbehandlaren 2: Skapa knappar
▪ private void createGUI() {
frame.setLayout(new MigLayout(
“”,
“[grow,fill]”,
“[]0[grow,fill]0[]”
));
…
}
Vårt mål…
28
Layoutparametrar
Inget här…
Kolumnparametrar
Varje kolumn anges i []
Kolumnen kan växa (grow),
och ska alltid fylla (fill)
tillgängligt utrymme
Radparametrar
Första raden: [] (default)
Mellanrum: 0 pixel
Andra raden: Grow, fill
Mellanrum: 0 pixel
Tredje raden: [] (default)
jonkv@ida
Ordbehandlaren 3: Sätta layouthanterare
29
jonkv@ida
Ordbehandlaren 4: Ramar
Alla komponenter kan ha en ram, som implementerar gränssnittet Border.
Använd BorderFactory för vanliga ramtyper.
▪ private void createGUI() {
frame.setLayout(new MigLayout(…));
= new JTextPane();
this.text
this.status
= new JLabel("Status: OK");
text.setBorder(BorderFactory.createEmptyBorder(4,4,4,4));
status.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEtchedBorder(),
BorderFactory.createEmptyBorder(2,2,2,2)
));
EmptyBorder =
tomt utrymme
(marginaler)
CompoundBorder
sätter ihop ramar:
Ytterst en etsad ram
Innerst en marginal
http://docs.oracle.com/javase/tutorial/
uiswing/components/border.html

30
jonkv@ida
Ordbehandlaren 5: Scrollning
http://docs.oracle.com/javase/tutorial/
uiswing/components/scrollpane.html
Textfältet måste kunna scrollas
 I vissa system: "Inbyggt" i textfältet
 I Java: Lägg komponenten i en JScrollPane
▪ Samma hantering av scrollning för alla komponenter
▪ private void createGUI() {
…
frame.add(createButtonPanel(),
“wrap”);
frame.add(new JScrollPane(text), “wrap”);
frame.add(status,
“wrap”);
}
Fönster
Menyrad
Meny1
Val1
Val2
ContentPane
Meny2
Val3
Panel
Knapp1
Knapp2
JScrollPane
Statusrad
Textfält
▪ private void createMenus() {
final JMenu file = new JMenu("File");
file.add(new JMenuItem("Open", 'O'));
file.add(new JMenuItem("Save As", 'A'));
file.addSeparator();
file.add(new JMenuItem("Print"));
32
http://docs.oracle.com/javase/tutorial/
uiswing/components/menus.html,
separator.html
// Tangentbordsstyrning
// Separator
final JMenu edit = new JMenu("Edit");
edit.add(new JMenuItem("Cut"));
edit.add(new JMenuItem("Copy"));
edit.add(new JMenuItem("Paste"));
final JMenu help = new JMenu("Help");
help.add(new JMenuItem("About WordProcessor 1.0"));
final JMenuBar bar = new JMenuBar();
bar.add(file);
bar.add(edit);
bar.add(Box.createHorizontalGlue());
bar.add(help);
frame.setJMenuBar(bar);
}
Separering
Skapar en osynlig
komponent, 0 pixel hög,
godtyckligt bred
jonkv@ida
Att skapa menyer
TDDC69 2011-2013: Allt på engelska
Använd tid för kursutveckling på bästa sätt…
TDDD78 2014-2015:
Inledande fö. på svenska
TDDD78 2014-2015:
Resten på engelska
Nästan helt omskrivet,
många fundamentala begrepp
Många justeringar,
huvudstrukturen behålls

How do we know if a button was pushed?
 TDDD73: Wait for a click
▪ Must know when to check
▪ Must handle everything ourselves – coordinates, …
35
jonkv@ida
Event Handling Principles

36
In some GUI systems:
 Tell the system what it should do when the button is clicked
 Go on with your own task
 When the button is pushed, another thread handles this asynchronously

(Almost) as if:
You tell someone else:
"If the button is pressed, do this"
Your assistant
starts looking for input
You keep doing
whatever you want to do next
Sees a button was pressed,
does what you asked
jonkv@ida
Event Handling Principles (2)

37
How to represent what happens and what to do about it?
 As event objects [händelseobjekt]…
// Standard Java class
public class MouseEvent extends InputEvent {
int x;
// Coordinates
int y;
int clickCount; // How many times did they click?
int button;
// With which mouse button?
…
}
Button clicked 
Our "assistant" creates
a new MouseEvent
jonkv@ida
Event Handling Principles (3)

How to represent what happens and what to do about it?
 Could we tell the component which function to call?
// Would work in some languages…
function printMessage() {
print "Hey! Someone clicked me!"
}
button.whenClicked(printMessage);
Java is object-oriented,
has no functions outside classes
Java 8 has new ”magic syntax”
that lets us do something similar
To see what really happens,
and to link this to interesting design patterns,
we will avoid this syntax for now!
38
jonkv@ida
Event Handling Principles (4)

39
jonkv@ida
Event Handling Principles (5)
How to represent what happens and what to do about it?
 We'll give the button an object whose methods it can call!
// Standard Java interface
public interface MouseListener extends EventListener {
public void mouseClicked(MouseEvent e);
Java is manifestly typed,
public void mousePressed(MouseEvent e);
must define a type
…
for the object …
}
We create a class
implementing MouseListener
// Our own class
public class MyListener implements MouseListener {
public void mouseClicked(MouseEvent e) {
System.out.println("Hey! Someone clicked me!"); We give our "assistant"
}
a MyListener object
}
whose methods it can call
when something happens

Every component has a list of Listeners
// (This is a simplification…)
public class Component {
private List<MouseListener> mouseListeners;
public void addMouseListener(MouseListener ml) {
mouseListeners.add(ml);
}
…
}
 We can add our own listener to the list
// Our own class
public class MyGUI {
public void createGUI() {
MouseListener ml = new MyListener();
theButton.addMouseListener(ml);
}
}
40
jonkv@ida
Event Handling Principles (6)

When a mouse button has been pressed:
AWT receives ”raw” keyboard/mouse input from the OS
 In a background event dispatch thread (your "assistant")
 Generates low-level event objects: MouseEvent, KeyEvent
public class MouseEvent extends InputEvent {
int x;
// Coordinates
int y;
int clickCount; // How many times did they click?
int button;
// With which mouse button?
…
}
41
jonkv@ida
Events 1: Introduction

When a button has been pressed:
AWT receives ”raw” keyboard/mouse input from the OS
 In a background event dispatch thread (your "assistant")
 Generates low-level event objects: MouseEvent, KeyEvent
Asks the relevant component to process the event
 Mouse click  sent to component that was clicked
// AWT finds out which component is responsible
MouseEvent event = …;
Component comp = findOutWhoWasClicked();
// AWT asks the component to take care of the event
comp.processEvent(event);
42
jonkv@ida
Events 2: Introduction

43
When a button has been pressed:
Asks the relevant component to process the event
 Mouse click  sent to component that was clicked
Event processing notifies (calls a method in) every listener
 Including our registered MyListener
public class Component {
protected void processMouseEvent(MouseEvent event) {
for (MouseListener listener: MouseListeners) {
if (event.getID() == MouseEvent.MOUSE_PRESSED)
listener.mousePressed(e);
One event at a time!
…
}
If your listener takes a long time,
}
the UI will freeze. If so,
}
let the listener start a thread!
jonkv@ida
Events 3: Introduction

Uses a design pattern called Observer!
 Components are observable,
can tell others when something happens
 Listeners are observers, observing specific event types
44
jonkv@ida
Events 4: Design Pattern

45
How are listeners used?
▪ public class WordProcessor {
private JTextPane text;
…
public JPanel createButtonPanel() {
Create local variables
final JPanel buttons = new JPanel();
for the buttons,
final JButton bold
= new JButton("B");
so you can refer to
buttons.setLayout(…);
them later!
buttons.add(bold);
bold.addActionListener(new BoldListener(text));
}
}
▪ public class BoldListener implements ActionListener {
private final JTextPane pane;
public BoldListener(JTextPane pane) {this.pane = pane;} A lot of trivial code
around
public void actionPerformed(ActionEvent event) {
“the real work”
// … Make the selected text bold …
}
Called by the event system in the
}
event dispatch thread when Bold is pressed
jonkv@ida
WP Events 1: Top-Level Class

46
jonkv@ida
WP Events 2: Inner Class
Alternative: Inner Class
▪ public class WordProcessor {
private JTextPane text;
…
public JPanel createButtonPanel() {
final JPanel buttons = new JPanel();
final JButton bold
= new JButton("B");
buttons.setLayout(…);
buttons.add(bold);
class BoldListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
foo(text.getText()); // … Make the text bold …
}
}
bold.addActionListener(new BoldListener());
}
}
Define a class inside
another – even inside a
method!
Gives access to fields
of the enclosing class,
final local variables
of the method
We still need a name…

47
Alternative: Anonymous Inner Class
▪ public class WordProcessor {
private JTextPane text;
…
public JPanel createButtonPanel() {
final JPanel buttons = new JPanel();
final JButton bold
= new JButton("B");
buttons.setLayout(…);
buttons.add(bold);
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent event) {
foo(text.getText()); // … Make the text bold …
}
Special “syntactic sugar”!
};
bold.addActionListener(al);
1) Declares an unnamed class
}
implementing ActionListener
}
2) Gives it an implementation for
actionPerformed()
3) Creates a new object of this unnamed class
jonkv@ida
WP Events 3: Anonymous
48
First alternative: One listener per button
bold.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Bold");
You know where the event
}
came from – the bold button
});
italics.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Italics");
A little bit of overhead
}
from defining many classes
});
// ... and so on ...
jonkv@ida
WP Events 4: One Listener per Button
49
Second alternative: A combined listener class
final ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == bold) {
Since many components share
System.out.println("Bold");
listeners, you must
} else if (e.getSource() == italics) {
check the source
System.out.println("Italics");
of each event
}
}
};
bold.addActionListener(al);
italics.addActionListener(al);
// ... and so on ...
}
return buttons;
jonkv@ida
WP Events 5: A Shared Listener Class

50
Alternative for actions that can be triggered from many places:
 Use Action (interface) and AbstractAction (helper class)!
▪ Action boldAction = new AbstractAction("Action Name") {
// Instance initializer to set some (optional) values
{
putValue(SHORT_DESCRIPTION, "Tool Tip Text");
putValue(SMALL_ICON,
new ImageIcon("icon.gif"));
putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_A)); //underlined
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("control F2"));
}
public void actionPerformed(ActionEvent evt) {
http://docs.oracle.com/javase/tutorial/
// Perform action
uiswing/misc/action.html
}
};
 Many components can be constructed from an action object
▪ panel.add(new JButton(boldAction));
editMenu.add(boldAction);
toolbar.add(boldAction);
jonkv@ida
Actions

Event handling for menus: No difference in principle
 final JMenuItem open = new JMenuItem("Open");
fileMenu.add(open);
open.addActionListener(…);
51
jonkv@ida
Menu Events
 Some of the most important listeners:
▪ ActionListener
Button pushed, menu item selected, …
▪ AdjustmentListener
Slider or scroll bar adjusted
▪ ItemListener
Items selected in list
▪ MouseListener
Mouse button pushed/released, …
▪ MouseMotionListener
Mouse pointer moved
▪ KeyListener
Key pressed, typed, released
Sent to the component that has keyboard focus
If not processed, passed on to its container, etc.
To react directly to keyboard input, see:
http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
http://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html
52
jonkv@ida
Event Listener Overview
A simpler replacement for key listeners
KeyStroke: A combination of keys
(X, Ctrl-Shift-Z, …)
Each component's InputMap
maps keystrokes to action names
The name of an action
(a String)
A component's ActionMap
maps keystrokes to action names
Action: Contains code to be performed
when the keys are pressed
54
jonkv@ida
Key Bindings: The Concept

55
Alternative to KeyListener: Key Bindings
class MyGameComponent extends JComponent {
class MoveLeftAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
…do something…
}
}
private void addBindings() {
Action moveToTheLeft = new MoveLeftAction();
getActionMap().put(”moveLeft”, moveToTheLeft);
}
}
Define a class
implementing Action
(in one of many ways…)
Create an Action object
(can be used in menus
or other places as well)
Define which Action is called
for the action name
”moveLeft”
jonkv@ida
Key Bindings: ActionMap

56
Alternative to KeyListener: Key Bindings
Works if keyboard focus
class MyGameComponent extends JComponent {
is in THIS component
private void addBindings1() {
InputMap map1 = getInputMap(JComponent.WHEN_FOCUSED);
map1.put(KeyStroke.getKeyStroke(”LEFT”), ”moveLeft”);
Check the KeyStroke Javadoc
for examples
}
…
https://docs.oracle.com/javase/8/docs/api/javax/swing/KeyStroke.html
An action name
jonkv@ida
Key Bindings: InputMap

57
Alternative to KeyListener: Key Bindings
class MyGameComponent extends JComponent {
Works if keyboard focus
private void addBindings2() {
is here or in a subcomponent
InputMap map2 = getInputMap(
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
map2.put(KeyStroke.getKeyStroke(”released RIGHT”, ”stopRight”));
Works if keyboard focus
is in the same window
InputMap map3 = getInputMap(
JComponent.WHEN_IN_FOCUSED_WINDOW);
map3.put(KeyStroke.getKeyStroke(”Ctrl F2”, ”quit”));
}
Fönster
Menyrad
Meny1
Val1
ContentPane
Meny2
Val2
Val3
Panel
Knapp1
Knapp2
JScrollPane
Textfält
Statusrad
jonkv@ida
Key Bindings: InputMap

Standard dialog windows: JOptionPane
 Simple question:
▪ String input = JOptionPane.showInputDialog("Please input a value");
 Can specify a frame that owns the dialog
▪ Blocks input to this frame
▪ JOptionPane.showMessageDialog(frame,
"Eggs are not supposed to be green.");
 Can give additional options
▪ JOptionPane.showMessageDialog(frame,
"Eggs are not supposed to be green.",
"Inane warning",
JOptionPane.WARNING_MESSAGE);
59
jonkv@ida
JOptionPane

60
Complex dialog windows
▪ // Custom button text
Object[] options = {
"Yes, please",
"No, thanks",
"No eggs, no ham!"
};
int optionChosen = JOptionPane.showOptionDialog(
frameParent, // A window that “owns” the dialog
"Would you like some green eggs to go with that ham?",
"A Silly Question",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
// Custom text
options[2]
// Default choice
)
http://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html
jonkv@ida
JOptionPane (2)

61
Additional dialog windows:
 File dialogs
▪ http://docs.oracle.com/javase/tutorial/uiswing/components/filechooser.html
 Color selection dialogs
▪ http://docs.oracle.com/javase/tutorial/uiswing/components/colorchooser.html
jonkv@ida
File and Color Dialogs

To close a window: Call frame.dispose().
 Frees all associated resources

To configure what the close button does:
 Use myframe.setDefaultCloseOperation(x), where x is…
▪ WindowConstants.HIDE_ON_CLOSE (default, hides but does not dispose)
▪ WindowConstants.DO_NOTHING_ON_CLOSE
▪ WindowConstants.DISPOSE_ON_CLOSE
▪ WindowConstants.EXIT_ON_CLOSE
63
jonkv@ida
Closing Windows 1

64
To add an "are you sure?" dialog:
 Use DO_NOTHING_ON_CLOSE
 Add a WindowListener
package java.awt.event;
public interface WindowListener extends EventListener {
public void windowOpened(WindowEvent e);
public void windowClosing(WindowEvent e);
public void windowClosed(WindowEvent e);
public void windowIconified(WindowEvent e);
public void windowDeiconified(WindowEvent e);
public void windowActivated(WindowEvent e);
public void windowDeactivated(WindowEvent e);
}
Called when the close button
is pressed
jonkv@ida
WindowListener

65
Don't want to implement every method?
 Extend WindowAdapter
package java.awt.event;
public class WindowAdapter implements WindowListener {
public void windowOpened(WindowEvent e) { }
public void windowClosing(WindowEvent e) { }
public void windowClosed(WindowEvent e) { }
public void windowIconified(WindowEvent e) { }
public void windowDeiconified(WindowEvent e) { }
public void windowActivated(WindowEvent e) { }
public void windowDeactivated(WindowEvent e) { }
}
Empty implementations
of all methods
jonkv@ida
WindowAdapter

66
Adding an appropriate listener:
public class GUIcreator {
private class CloseButtonHandler extends WindowAdapter {
public void windowClosing(final WindowEvent e) {
int answer = JOptionPane.showConfirmDialog
(f, "Do you really want to quit?", "Quit?", JOptionPane.YES_NO_OPTION);
if (answer == JOptionPane.YES_OPTION) {
System.exit(0);
}
}
}
public static void addCloseListener(final Frame f) {
f.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
f.addWindowListener(new CloseButtonHandler());
}
}
}
jonkv@ida
Adding a Dialog

67
An alternative solution (inner class):
public class GUIcreator {
public static void addCloseListener(final Frame f) {
f.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
f.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(final WindowEvent e) {
int answer = JOptionPane.showConfirmDialog
(f, "Do you really want to quit?", "Quit?",
JOptionPane.YES_NO_OPTION);
if (answer == JOptionPane.YES_OPTION) {
System.exit(0);
}
}
});
}
}
jonkv@ida
Alternative Solution

69
jonkv@ida
Debugging a GUI Program
You can view the component hierarchy
 Select a frame (window) and press Ctrl-Shift-F1
 The component hierarchy is dumped to standard error
 app.TestFrame[frame0,0,0,640x480,layout=java.awt.BorderLayout,resizable,title=,defaul
tCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,4,25,632x451,lay
out=javax.swing.JRootPane$RootLayout,alignmentX=null,alignmentY=null,border=,flag
s=3666,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
 javax.swing.JRootPane[,4,25,632x451,layout=javax.swing.JRootPane$RootLayout,ali
gnmentX=null,alignmentY=null,border=,flags=3666,maximumSize=,minimumSize=,p
referredSize=]
▪ …
▪ javax.swing.JPanel[null.contentPane,0,0,632x451,layout=javax.swing.JRootPane
$1,alignmentX=null,alignmentY=null,border=,flags=34,maximumSize=,minimu
mSize=,preferredSize=,defaultLayout=java.awt.FlowLayout[hgap=5,vgap=5,align
=center]]
 app.TestFrame$DateComponent[,0,0,632x451,alignmentX=null,alignmentY=
null,border=,flags=0,maximumSize=,minimumSize=,preferredSize=]

Swing: Can replace the look and feel dynamically
 Nimbus
(current Java
standard)
 Metal
(earlier Java
standard)
 Windows
classic
http://docs.oracle.com/javase/tutorial/
uiswing/lookandfeel/
70
jonkv@ida
Pluggable Look and Feel
Download