Sei sulla pagina 1di 26

10/9/2014

Method Overloading (1/4)

Method Overloading
Review

Can define multiple methods


of same name within a class,
as long as method signatures
are different

// this is an approximation of what Maths


// three max methods look like
public class Math {
// other code elided
public static int max(int a, int b) {
// return max of two ints
}

Example: java.lang.Math
static method max takes in
two numbers and returns the
greater of the two

public static float max(float a, float b) {


// return max of two floats
}

There are actually three max


methods-- one for ints, one
for floats, one for doubles

public static double max(double a,


double b){
// return max of two doubles
}
}

Method Overloading (2/4)


Methods in same class with
same name but different
parameter lists
When calling an overloaded
method, Java infers which
method you mean based on
parmeter list

// this is an approximation of what Maths


// three max methods look like
public class Math {
// other code elided
public static int max(int a, int b) {
// return max of two ints
}
public static float max(float a, float b) {
// return max of two floats
}

Thus cannot have two methods


with identical signatures but
different return typescompiler
error because Java cant
determine which to call!

Method Overloading (3/4)


Be careful not to confuse
overloading and overriding!
o override an inherited
method in a subclass: the
signatures (name; number,
types, and order of
parameters) must be the
same
o

public static double max(double a,


double b){
// return max of two doubles
}
}

// this is an approximation of what Maths


// three max methods look like
public class Math {
// other code elided
public static int max(int a, int b) {
// return max of two ints
}
public static float max(float a, float b) {
// return max of two floats
}

overload methods in the


same class: names are
same, but signatures must
be different

public static double max(double a,


double b){
// return max of two doubles
}
}

10/9/2014

Method Overloading (4/4)


If neither overriding nor overloading: Can use same name,
indeed signatures for methods in different classes
o Java can differentiate by type of instance on which
method is called during method resolution
o for example: if classes Car and Dog both have a move
method that takes in one parameter of type int, Java
knows to use the Dogs move when called on an
instance of Dog:
Dog dog = new Dog();

Method Overloading: Constructors


Even constructors can be
overloaded! Wardrobe class
has multiple constructors

public class Wardrobe {


private String _top;
private String _bottom;

A String (java.lang.String)
is a sequence of alphanumeric
characters, including space!
Example:

dog.move(1); //Dogs move method is called.


car.move(1); //Cars move method is called.

System.out.println(s);

Method Overloading: Example

public Wardrobe(String top) {


_top = top;
_bottom = Jeans;
}

String s = CS15 Rocks!;

Can use System.out.println


to print any string you want:

Car car = new Car();

public Wardrobe(String top, String bottom) {


_top = top;
_bottom = bottom;
}

public Wardrobe() {
_top = T-Shirt;
_bottom = Jeans;
}

Lecture 9

An overloaded method can call other overloaded methods


public class Plastic {
public Plastic(BurnBook myBurnBook) {
DirtySecret secret = myBurnBook.getDirtySecret();
this.backStab(secret);
}
public void backStab(DirtySecret secret) {
String victim = secret.getVictim(); //find out whose secret it is
this.backStab(victim, secret);
}
public void backStab(String victim, DirtySecret secret) {
//code to backstab elided (we dont teach you how to backstab!)
}
//other methods elided
}

Intro to Swing
0 of 95

10/9/2014

What is Swing?

Creating Applications from Scratch

Swing is an API (Application Programming


interface)
o part of core Java library

Until now, TAs took care of graphical


components for you

o used to create applications with 2D graphics


Frequently used classes in javax.swing package
o javax.swing.JFrame the main window used
by your app

Support code created JFrame, JPanels, all


graphical components

JFrame
JPanel
JButtons

o javax.swing.JPanel-- a canvas that contains


graphical components
o javax.swing.JButton-- a clickable button

From now on, youre in charge of this!


1 of 95

2 of 95

Pixels and Coordinate System

Graphical User Interfaces (GUIs)

(0, 0)

GUIs provide a usercontrolled (i.e.,


graphical) way to send
messages to a system
of objects

The screen is a grid of


pixels (tiny dots)
Integer Cartesian plane with:
o origin in upper-left corner
o y-axis increasing downward

Youll use Swing to


create your own GUIs
throughout the semester

o corresponds to Latin-based
languages writing order
3 of 95

pixels

4 of 95

10/9/2014

Pixels and Coordinate System


(0, 0)

Creating GUIs with Swing

Pattern: instantiate the


Swing components you
need and add them to
graphical containers

When working with Swing,


youll be able to set the size
and location of different
components (panels, buttons,
etc.) in pixels

Start with JFrame


Add JPanel to JFrame

The location of each


component will be the
location of its top left corner

JLabel

Hello, World!
JButtons

5 of 95

Creating GUIs with Swing

Well learn how to


customize layout later in
lecture

JPanel

Add JButtons,
JLabels, etc. to JPanel
pixels

Swing uses a default


layout to arrange
components in a JFrame
or JPanel

JFrame

6 of 95

Our First Swing Application


JFrame

JFrame

Spec: app that contains text


reading CS15 Rocks! and
button that randomly
changes the texts color with
every click

JPanel
JLabel

Hello, World!
JButtons

Useful classes: JFrame,


JPanel, JLabel, JButton,
and ActionListener

For now, let Swing do it


for us
7 of 95

JLabel

JPanel

JButton

8 of 95

10/9/2014

DEMO: ColorTextApp

Process
JFrame

1. Create a top-level App class that


contains an instance of JFrame
JLabel

JPanel

2. Create a subclass of JPanel that


contains an instance of JButton and
an instance of JLabel
3. Add an instance of your JPanel
subclass to the JFrame

JButton

JFrame

JLabel

JPanel

JButton

4. Set up an ActionListener that


changes the labels color each time
the button is clicked
9 of 95

10 of 95

Top-level Class: ColorTextApp

Top-level Class: ColorTextApp

public class ColorTextApp {

public class ColorTextApp {

public ColorTextApp() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);

This is our top-level


class
It contains the JFrame
(window in which the
app will display) as a
component

frame.setVisible(true);

public static void main(String[] args) {


new ColorTextApp();
}

11 of 95

public ColorTextApp() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);

First we instantiate a
JFrame, which we store in
local variable frame

Note: these slides will omit


import statements at top of
file
}

frame.setVisible(true);

public static void main(String[] args) {


new ColorTextApp();
}

12 of 95

10/9/2014

Top-level Class: ColorTextApp

Next we call setDefaultCloseOperation on


our JFrame

This method specifies what happens when


user hits x in corner of the JFrame

Pass in constant JFrame.EXIT_ON_CLOSE


as an argument so app will quit when we
press the x

Swing magic keeps JFrames and their


contents alive as long as the x is not
pressed, so they will not be garbagecollected! (Java GCs variables when they
go out of scope cease to exist)

Top-level Class: ColorTextApp

public class ColorTextApp {


public ColorTextApp() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
}

frame.setVisible(true);

public static void main(String[] args) {


new ColorTextApp();
}

public class ColorTextApp {

Finally, we call the method


setVisible on our JFrame

public ColorTextApp() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);

Pass in boolean value true


as an argument
This makes the JFrame show
up!

Pro tip: Always call this


method last to avoid nasty
layout bugs

frame.setVisible(true);

public static void main(String[] args) {


new ColorTextApp();
}

13 of 95

JPanel Subclass: ColorTextPanel

Process
1. Create a top-level App class that
contains an instance of JFrame

JFrame

2. Create a subclass of JPanel that


contains an instance of JButton
and an instance of JLabel
3. Add an instance of your JPanel
subclass to the JFrame

14 of 95

JLabel

JPanel

The class
ColorTextPanel is a
JPanel: our canvas that
may contain other Swing
GUI components
Weve specialized this
class to contain and
display a JLabel and a
Jbutton (local vars)

JButton

4. Set up an ActionListener that


changes the labels color each time
the button is clicked
15 of 95

public class ColorTextPanel extends JPanel {


public ColorTextPanel() {
JLabel label = new JLabel("CS15 Rocks!");
JButton button = new JButton("Random Color");

Dimension panelSize = new Dimension(150, 75);


this.setPreferredSize(panelSize);
this.add(label);
this.add(button);

16 of 95

10/9/2014

JPanel Subclass: ColorTextPanel


First, we instantiate a
JLabel and JButton
In each case, we pass in
a String as an argument
This String is the text we
want the label/button to
display
Here we pass the
string as a literal;
could also pass a
string variable

JPanel Subclass: ColorTextPanel


Now we set the preferred
size of our panel

public class ColorTextPanel extends JPanel {


public ColorTextPanel() {
JLabel label = new JLabel("CS15 Rocks!");
JButton button = new JButton("Random Color");

Dimension panelSize = new Dimension(150, 75);


this.setPreferredSize(panelSize);
this.add(label);
this.add(button);

public class ColorTextPanel extends JPanel {

First, instantiate a Dimension


(object that represents a
width and height, in pixels)

public ColorTextPanel() {
JLabel label = new JLabel("CS15 Rocks!");
JButton button = new JButton("Random Color");

First argument is width,


second is height
Then call method
setPreferredSize on panel,
passing in the Dimension as
an argument

Dimension panelSize = new Dimension(150, 75);


this.setPreferredSize(panelSize);
this.add(label);
this.add(button);

17 of 95

The ColorTextPanel class


Finally, we add the label
and button to the panel by
calling the panels add
method

Process
1. Create a top-level App class that
contains an instance of JFrame

public class ColorTextPanel extends JPanel {


public ColorTextPanel() {
JLabel label = new JLabel("CS15 Rocks!");
JButton button = new JButton("Random Color");

This is a necessary step


for the label and button to
show up!
}

18 of 95

Dimension panelSize = new Dimension(150, 75);


this.setPreferredSize(panelSize);
this.add(label);
this.add(button);

19 of 95

JFrame

2. Create a subclass of JPanel that


contains an instance of JButton and
an instance of JLabel
3. Add an instance of your JPanel
subclass to the JFrame

JLabel

JPanel

JButton

4. Set up an ActionListener that


changes the labels color each time
the button is clicked
20 of 95

10/9/2014

The ColorTextApp class


First, instantiate a new
ColorTextPanel

public ColorTextApp() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);

Then, add it to the JFrame by


calling the add method

JPanel panel = new ColorTextPanel();


frame.add(panel);
frame.pack();

Finally, call the method pack


on the JFrame
o pack tells frame to resize
itself based on the
preferred sizes of the
components inside it

Process

public class ColorTextApp {

frame.setVisible(true);

public static void main(String[] args) {


new ColorTextApp();
}

JFrame

1. Create a top-level App class that


contains an instance of JFrame
2. Create a subclass of JPanel that
contains an instance of JButton and
an instance of JLabel
3. Add an instance of your JPanel
subclass to the JFrame

JLabel

JPanel

JButton

4. Set up an ActionListener that


changes the labels color each
time the button is clicked
22 of 95

21 of 95

Responding to User Input

ActionListeners

Need a way to respond to stimulus of button


being clicked

Whenever a JButton is clicked, it generates a


java.awt.event.ActionEvent

We refer to this as event handling

We define class that listens for ActionEvents: must


implement interface java.awt.event.ActionListener

o A source generates an event (like a


mouse click or a key press) and notifies
all registered listeners

ActionListener interface declares method:


public void actionPerformed(ActionEvent e);

o Each listener has a method for


responding to the event
o stimulus-response mechanism that allows
multiple listeners to respond

This method must be defined in our listener class


o called by Java whenever an ActionEvent is fired
23 of 95

o specifies response to event

24 of 95

10/9/2014

ActionListeners
JButton

Our ActionListener: ColorListener

ActionListener

ActionEvent e

public class ColorListener implements ActionListener {


private JLabel _label; //associated label

Click!

Our listener class is


ColorListener

public void actionPerformed( ActionEvent e) {

// Respond here; may or may not use ActionEvent


// (print something to the console,
// tell a JLabel to change color, etc.)

public ColorListener(JLabel label) {


_label = label; }

Its job is to listen for


ActionEvents and
respond to them by
changing the color of a
JLabel
}

@Override
public void actionPerformed(ActionEvent e) {
int red = (int) (Math.random()*256);
int green = (int) (Math.random()*256);
int blue = (int) (Math.random()*256);
Color random = new Color(red, green, blue);
_label.setForeground(random);
}

25 of 95

Our ActionListener: ColorListener

26 of 95

Our ActionListener: ColorListener

public class ColorListener implements ActionListener {


private JLabel _label;

Associated with a JLabel,


which it refers to as
_label-- a ColorListener
will be passed the JLabel
whose color it should
change
When ActionEvent is
detected, will change
_labels color

public ColorListener(JLabel label) {


_label = label;
}

public class ColorListener implements ActionListener {


private JLabel _label;
public ColorListener(JLabel label) {
_label = label;
}

actionPerformed defines
response to ActionEvent

@Override
public void actionPerformed(ActionEvent e) {
int red = (int) (Math.random()*256);
int green = (int) (Math.random()*256);
int blue = (int) (Math.random()*256);
Color random = new Color(red, green, blue);
_label.setForeground(random);
}
27 of 95

In this case, we want it to


generate a random color,
and then set _label to that
color
}

@Override
public void actionPerformed(ActionEvent e) {
int red = (int) (Math.random()*256);
int green = (int) (Math.random()*256);
int blue = (int) (Math.random()*256);
Color random = new Color(red, green, blue);
_label.setForeground(random);
}
28 of 95

10/9/2014

Our ActionListener: ColorListener


public class ColorListener implements ActionListener {
private JLabel _label;

Use Math.random() to
generate three random ints
0-255
Use them as RGB values
for a new Color
Call JLabel method
setForeground on _label
to set its color to the random
color weve created
}

public ColorListener(JLabel label) {


_label = label;
}

Adding ActionListeners

First, instantiate a ColorListener


public class ColorTextPanel extends JPanel {
Pass in label as argument to
public ColorTextPanel() {
listeners constructor so it knows to
JLabel label = new JLabel("CS15 Rocks!");
change labels color
JButton button = new JButton("Random Color");
Next, use method
ColorListener listener =
addActionListener to add our
new ColorListener(label);
ColorListener to button
button.addActionListener(listener);
Typical pattern: listeners are
Dimension panelSize = new Dimension(150, 75);
added to the event-emitting
this.setPreferredSize(panelSize);
component they listen to
this.add(label);
Whenever button emits an
this.add(button);
}
ActionEvent, listener will hear and
}
respond to it

@Override
public void actionPerformed(ActionEvent e) {
int red = (int) (Math.random()*256);
int green = (int) (Math.random()*256);
int blue = (int) (Math.random()*256);
Color random = new Color(red, green, blue);
_label.setForeground(random);
}

29 of 95

30 of 95

public class ColorTextPanel extends JPanel {

The Whole App

Process
JFrame

public class ColorTextApp {

1. Create a top-level App class that


contains an instance of JFrame

public ColorTextApp() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);

2. Create a subclass of JFrame that


contains an instance of JButton and
an instance of JLabel

JPanel panel = new ColorTextPanel();


frame.add(panel);
frame.pack();

JLabel

3. Add a JPanel to the JFrame


4. Set up an ActionListener that
changes the labels color each time
the button is clicked

JPanel

JButton
}

31 of 95

public ColorTextPanel() {
JLabel label = new JLabel("CS15 Rocks!");
JButton button = new JButton("Random Color");
ColorListener listener = new ColorListener(label);
button.addActionListener(listener);
Dimension panelSize = new Dimension(150, 75);
this.setPreferredSize(panelSize);
this.add(label);
this.add(button);
}

public class ColorListener implements ActionListener {


private JLabel _label;
public ColorListener(JLabel label) {
_label = label;
}

frame.setVisible(true);

public static void main(String[] args) {


new ColorTextApp();
}

@Override
public void actionPerformed(ActionEvent e) {
int red = (int) (Math.random()*256);
int green = (int) (Math.random()*256);
int blue = (int) (Math.random()*256);
Color random = new Color(red, green, blue);
_label.setForeground(random);
}

32 of 95

10

10/9/2014

Logical vs. Graphical Containment


JFrame

Putting It All Together

ColorTextApp

ColorTextApp
ColorTextPanel

JFrame

JLabel
ColorTextPanel

JButton

JLabel

JFrame
JButton

Useful classes: JFrame,


JPanel, JLabel, Timer,
ActionListener

JPanel

JButton

Graphically, the ColorTextPanel is contained within the JFrame, but logically, both are
contained together in a top-level App class; App and ColorListener arent graphic!

Logical containment is based on where objects are created, while graphical is based on swing
elements being added to other swing elements via the add() method

Note: The JButton also has a reference to ColorListener, but this reference is omitted from our
diagram to avoid excessive complexity.

34 of 95

DEMO: Clock

Another Swing App: Clock


Specifications: App
should display the
current date and time,
updating every second

ColorListener

ColorListener
33 of 95

JLabel

JFrame

JPanel

JLabel

35 of 95

36 of 95

11

10/9/2014

Using Timers

Using Timers
The class javax.swing.Timer comes in handy when we
need to perform a task repeatedly at regular intervals
When we instantiate a Timer, we pass it:
o
o

ActionListener

ActionEvent e
Timer
Tick!

An int (number of milliseconds between Timer ticks)


An ActionListener that should be notified when the
Timer emits an ActionEvent (on every tick)

public void actionPerformed( ActionEvent e ) {

Were going to use a Timer to update the time displayed


on our JLabel at regular intervals

// Respond to ActionEvent here!


// (print something to the console, tell
// a JLabel to update its text, etc.)

38 of 95

37 of 95

Top-level Class: Clock

Process: Clock
1. Create top-level class that
contains a JFrame

public class Clock {

JFrame

2. Write a subclass of JPanel that


contains a JLabel. Add an
instance of it to our JFrame
3. Write a class that implements
ActionListener-- it should know
about a JLabel and update its
text on every ActionEvent
4. Instantiate a listener and a Timer,
and start the Timer

public Clock() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);

As in the previous
example, we create a toplevel class that contains a
JFrame
JPanel

Specify closing behavior of


JFrame the same way we
did last time

JLabel

}
39 of 95

frame.pack();
frame.setVisible(true);

public static void main(String[] args) {


new Clock();
}
40 of 95

12

10/9/2014

Process: Clock

Top-level Class: Clock

1. Create top-level class that


contains a JFrame

public class Clock {

Call pack on the JFrame so


it will resize itself based on
its contents (which well be
adding soon)

public Clock() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);

Last, make the frame show


up by calling
setVisible(true);

frame.pack();
frame.setVisible(true);

public static void main(String[] args) {


new Clock();
}
41 of 95

JPanel subclass: ClockPanel


Well call our JPanel
subclass ClockPanel

Call setPreferredSize on
panel, passing in the
Dimension we created

3. Write a class that implements


ActionListener -- it should
know about a JLabel and update
its text on every ActionEvent

JLabel

42 of 95

JPanel subclass: ClockPanel


public class ClockPanel extends JPanel {

public ClockPanel() {
Dimension panelSize =
new Dimension(250, 50);
this.setPreferredSize(panelSize);

public ClockPanel() {
Dimension panelSize =
new Dimension(250, 50);
this.setPreferredSize(panelSize);

Instantiate a JLabel, which


will be used to display
current time
Add the JLabel to our
panel

JLabel timeLabel = new JLabel();


this.add(timeLabel);
}

JPanel

4. Instantiate a listener and a Timer,


and start the Timer

public class ClockPanel extends JPanel {

As in previous example,
create a Dimension to
represent desired width and
height of panel

JFrame

2. Write a subclass of JPanel that


contains a JLabel. Add an
instance of it to our JFrame

JLabel timeLabel = new JLabel();


this.add(timeLabel);
}

43 of 95

44 of 95

13

10/9/2014

Process: Clock

Adding a ClockPanel to our JFrame

1. Create top-level class that


contains a JFrame

public class Clock {


public Clock() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);

Back in our top-level class

2. Write a subclass of JPanel that


contains a JLabel. Add an
instance of it to our JFrame

ClockPanel panel = new ClockPanel();


frame.add(panel);

After instantiating our


JFrame, we instantiate a
ClockPanel and add it to
the frame

frame.pack();
frame.setVisible(true);

public static void main(String[] args) {


new Clock();
}
45 of 95

Our ActionListener: TimerListener


A TimerListeners job will
be responding to
ActionEvents fired by a
Timer

public class TimerListener


implements ActionListener {
private JLabel _timeLabel; //associated label
public TimerListener(JLabel label) {
_timeLabel = label; }

Knows about a particular


JLabel, whose text it will
modify with every
ActionEvent
}

@Override
public void actionPerformed(ActionEvent e) {
long currTime = System.currentTimeMillis();
Date now = new Date(currTime);
_timeLabel.setText(now.toString());
}
47 of 95

3. Write a class that implements


ActionListener-- it should
know about a JLabel and
update its text on every
ActionEvent

JFrame

JPanel

JLabel

4. Instantiate a listener and a Timer,


and start the Timer

46 of 95

Our ActionListener: TimerListener


When ActionEvent fires, we
first determine current date
and time

public class TimerListener


implements ActionListener {
private JLabel _timeLabel;
public TimerListener(JLabel label) {
_timeLabel = label;
}

System.currentTimeMillis
returns number of
milliseconds elapsed since
midnight January 1, 1970
Can convert this number to
the actual date and time by
passing it into a new
java.util.Date

@Override
public void actionPerformed(ActionEvent e) {
long currTime = System.currentTimeMillis();
Date now = new Date(currTime);
_timeLabel.setText(now.toString());
}
48 of 95

14

10/9/2014

Our ActionListener: TimerListener


Next, we convert our Date
object to a String using its
toString method

1. Create top-level class that


contains a JFrame

public class TimerListener


implements ActionListener {
private JLabel _timeLabel;

@Override
public void actionPerformed(ActionEvent e) {
long currTime = System.currentTimeMillis();
Date now = new Date(currTime);
_timeLabel.setText(now.toString());
}

49 of 95

Instantiating a TimerListener
In constructor of
ClockPanel class, we
instantiate a new
TimerListener

JPanel

JLabel

4. Instantiate a listener and a


Timer, and start the Timer

Next, instantiate a new Timer,


and store it in instance
variable _timer
o first argument is number of
ms between ticks

JLabel timeLabel = new JLabel();


this.add(timeLabel);
TimerListener listener =
new TimerListener(timeLabel);
_timer = new Timer(100, listener);
_timer.start();
}

3. Write a class that implements


ActionListener-- it should know
about a JLabel and update its
text on every ActionEvent

50 of 95

Instantiating and starting a Timer

public class ClockPanel extends JPanel {


private Timer _timer;
public ClockPanel() {
Dimension panelSize =
new Dimension(250, 50);
this.setPreferredSize(panelSize);

Pass in our JLabel,


timeLabel, as an argument
so the TimerListener will
update its text

JFrame

2. Write a subclass of JPanel that


contains a JLabel. Add an
instance of it to our JFrame

public TimerListener(JLabel label) {


_timeLabel = label;
}

We pass the resulting date


string into _timeLabels
setText method to update
_timeLabels text

Process: Clock

}
51 of 95

public class ClockPanel extends JPanel {


private Timer _timer;
public ClockPanel() {
Dimension panelSize =
new Dimension(250, 50);
this.setPreferredSize(panelSize);
JLabel timeLabel = new JLabel();
this.add(timeLabel);

o second argument is the


listener that will be notified
on every tick

TimerListener listener =
new TimerListener(timeLabel);
_timer = new Timer(100, listener);
_timer.start();

Dont forget to call start on


the Timer!
}

}
52 of 95

15

10/9/2014

The Whole App

public class ClockPanel extends JPanel {


private Timer _timer;
public ClockPanel() {
Dimension panelSize = new Dimension(250, 50);
this.setPreferredSize(panelSize);

public class Clock {


public Clock() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
ClockPanel panel = new ClockPanel();
frame.add(panel);

Putting It All Together: Clock

JLabel timeLabel = new JLabel();


this.add(timeLabel);

Clock

TimerListener listener = new TimerListener(timeLabel);


_timer = new Timer(100, listener);
_timer.start();

}
}
public class TimerListener
implements ActionListener {
private JLabel _timeLabel;

frame.pack();
frame.setVisible(true);

JFrame

ClockPanel

public TimerListener(JLabel label) {


_timeLabel = label;
}

public static void main(String[] args) {


new Clock();
}

@Override
public void actionPerformed(ActionEvent e) {
long currTime = System.currentTimeMillis();
Date now = new Date(currTime);
_timeLabel.setText(now.toString());
}

JLabel

TimerListener

53 of 95

Timer

54 of 95

DEMO: ColorPanelApp

A Third Swing App: ColorPanelApp


JFrame

Specification: An app
with three sliders that
the user can drag to
change the RGB values
of the background color
Useful classes: JFrame,
JPanel, JSlider,
ChangeListener

JPanel

JSlider
55
of 95
62/102

56
of 95
63/102

16

10/9/2014

ChangeListeners

Using JSliders
A JSlider lets the user graphically select a value by
sliding an arrow within a bounded interval

ChangeListener

ChangeEvent e

One way to construct is by passing two ints (minimum


and maximum values) as arguments:

JSlider

JSlider slider = new JSlider(0, 30);

public void stateChanged(ChangeEvent e) {

To get the value of the slider, we can use the getValue


method
A JSlider emits ChangeEvents when value changes-to listen for them, we use a ChangeListener
57 of 95

// Respond to ChangeEvent here!


// (print something to the console, tell
// a JLabel to update its text, etc.)

58
of 95
65/102

64/102

Top-level Class: ColorPanelApp

Process: ColorPanelApp
JFrame

1. Create top-level class that


contains a JFrame

public class ColorPanelApp {

This top-level class is


almost identical to
those of the other
examples-- we follow
same pattern of setting
up JFrame

2. Write a subclass of JPanel that


contains three JSliders, add an
instance of it to the JFrame
3. Write a ChangeListener that
changes a JPanels color based
on value of a JSlider
4. Add ChangeListeners to the
JSliders

JPanel

public ColorPanelApp() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);

Instantiate JFrame, set


its close operation, call
pack and setVisible

JSlider

}
59
of 95
66/102

frame.pack();
frame.setVisible(true);

public static void main(String[] args) {


new ColorPanelApp();
}
60
of 95
67/102

17

10/9/2014

JPanel Subclass: ColorPanel

Process: ColorPanelApp
JFrame

1. Create top-level class that


contains a JFrame

ColorPanel is a
JPanel

2. Write a subclass of JPanel


that contains three JSliders,
add an instance of it to the
JFrame

JPanel

Want panel to start out


gray, so call method
setBackground

JSlider

Finally, add each slider


to panel

Adding a ColorPanelApp to the JFrame


public class ColorPanelApp {

public ColorPanel() {
Dimension panelSize = new Dimension(300, 150);
this.setPreferredSize(panelSize);
this.setBackground(Color.GRAY);
JSlider sliderRed = new JSlider(0, 255);
JSlider sliderGreen = new JSlider(0, 255);
JSlider sliderBlue = new JSlider(0, 255);

62
of 95
69/102

public class ColorPanel extends JPanel {

Arguments are
beginning/end of
sliders range: we give
each range 0-255 (one
byte/RGB channel)

this.add(sliderRed);
this.add(sliderGreen);
this.add(sliderBlue);

61
of 95
68/102

JPanel Subclass: ColorPanel


Instantiate three
JSliders: one to
control each channel
(red, green, and blue)

public ColorPanel() {
Dimension panelSize = new Dimension(300, 150);
this.setPreferredSize(panelSize);
this.setBackground(Color.GRAY);
JSlider sliderRed = new JSlider(0, 255);
JSlider sliderGreen = new JSlider(0, 255);
JSlider sliderBlue = new JSlider(0, 255);

As in other examples,
create a Dimension,
give it desired width
and height, then call
setPreferredSize

3. Write a ChangeListener that


changes a JPanels color based
on value of a JSlider
4. Add ChangeListeners to the
JSliders

public class ColorPanel extends JPanel {

this.add(sliderRed);
this.add(sliderGreen);
this.add(sliderBlue);

63
of 95
70/102

public ColorPanelApp() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);

Just as we did in
previous examples,
first instantiate a panel,
then call add to add it
to the JFrame

ColorPanel panel = new ColorPanel();


frame.add(panel);

frame.pack();
frame.setVisible(true);

public static void main(String[] args) {


new ColorPanelApp();
}
64
of 95
71/102

18

10/9/2014

Process: ColorPanelApp

Changing a JPanels Color


Every JPanel has a pair of accessor and mutator methods,
setBackground and getBackground

JFrame

1. Create top-level class that


contains a JFrame

We have three JSliders-- one to control each color channel of the


Jpanel. Each Jslider has its own listener

2. Write a subclass of JPanel that


contains three JSliders, add an
instance of it to the JFrame

When red sliders listener detects that its slider has been moved:
o it calls getBackground to ask the panel for its current color

3. Write a ChangeListener that


changes a JPanels color
based on value of a JSlider
4. Add ChangeListeners to the
JSliders

JPanel

o it creates a new instance of Color, using the R value from the


slider and the G and B values from the panels current
background color (since they havent changed)

JSlider
65
of 95
72/102

Our ChangeListener: SliderListener


A SliderListeners job is to
change the color of a JPanel
based on the value of a JSlider

public class SliderListener


implements ChangeListener {

Since JSliders emit


ChangeEvents whenever their
value changes, SliderListener
implements ChangeListener
interface
Defines method stateChanged.
SliderListener will be coded
generically so it can be used for
each slider

public SliderListener(JPanel panel, int channel,


JSlider slider){
_panel = panel;
_channel = channel;
_slider = slider;
}

public class SliderListener


implements ChangeListener {
private JPanel _panel;
private int _channel;
private JSlider _slider;

o The JPanel whose color


it should change

public SliderListener(JPanel panel, int channel,


JSlider slider){
_panel = panel;
_channel = channel;
_slider = slider;
}

o Which channel (red,


green, or blue) to modify
o Which slider it listens to
Well represent the channel as
an int: 0 means red, 1 means
green, 2 means blue

67
of 95
74/102

66
of 95
73/102

Our ChangeListener: SliderListener


To do its job, it needs to know
three things:

private JPanel _panel;


private int _channel;
private JSlider _slider;

@Override
public void stateChanged(ChangeEvent e) {
// implementation elided for now
}

o it calls setBackground, passing in the new Color

@Override
public void stateChanged(ChangeEvent e) {
// implementation elided for now
}

68
of 95
75/102

19

10/9/2014

The stateChanged method


// rest of class SliderListener elided for now
@Override
public void stateChanged(ChangeEvent e) {
Method is called whenever
val = _slider.getValue();
value of the listeners JSlider int
Color bg = _panel.getBackground();
Color newbg;
changes

Should modify the appropriate


color channel of the JPanels
background color
Must take in a ChangeEvent
as a parameter, because it is
required by the
ChangeListener interface;
doesnt use it in this case
}

switch(_channel){
case 0:
newbg = new Color(val, bg.getGreen(),
bg.getBlue());
break;
case 1:
newbg = new Color(bg.getRed(), val,
bg.getBlue());
break;
default:
newbg = new Color(bg.getRed(), bg.getGreen(),
val);
}
_panel.setBackground(newbg);
69
of 95
76/106

The stateChanged method


Next, we get the JPanels
current background color

// rest of class SliderListener elided for now


@Override
public void stateChanged(ChangeEvent e) {
int val = _slider.getValue();
Color bg = _panel.getBackground();
Color newbg;

switch(_channel){
case 0:
newbg = new Color(val, bg.getGreen(),
We declare a new Color, newBg,
bg.getBlue());
break;
to which well assign a different
case 1:
value based on which color
newbg = new Color(bg.getRed(), val,
bg.getBlue());
channel the listener is supposed
break;
to change
default:
newbg = new Color(bg.getRed(), bg.getGreen(),
val);
}
_panel.setBackground(newbg);
71
of 95
78/106
}

The stateChanged method

// rest of class SliderListener elided for now


@Override
public void stateChanged(ChangeEvent e) {
int val = _slider.getValue();
Color bg = _panel.getBackground();
Color newbg;

Need to determine new value of


JSlider
Since we know the source is the
JSlider, we can retrieve value
by calling getValue on _slider

switch(_channel){
case 0:
newbg = new Color(val, bg.getGreen(),
bg.getBlue());
break;
case 1:
newbg = new Color(bg.getRed(), val,
bg.getBlue());
break;
default:
newbg = new Color(bg.getRed(), bg.getGreen(),
val);
}
_panel.setBackground(newbg);
70
of 95
77/106

The stateChanged method


Depending on the value of
_channel, we set newBg to
different color

// rest of class SliderListener elided for now


@Override
public void stateChanged(ChangeEvent e) {
int val = _slider.getValue();
Color bg = _panel.getBackground();
a
Color newbg;

In each case, only the specified


color channel changes; we use
the gets for the values of the
unchanged channels
Once weve changed the
appropriate channel, we set the
JPanels background color to
newBg
}

switch(_channel){
case 0:
newbg = new Color(val, bg.getGreen(),
bg.getBlue());
break;
case 1:
newbg = new Color(bg.getRed(), val,
bg.getBlue());
break;
default:
newbg = new Color(bg.getRed(), bg.getGreen(),
val);
}
_panel.setBackground(newbg);
72
of 95
79/106

20

10/9/2014

Setting up our SliderListeners

Process: ColorPanelApp

public class ColorPanel extends JPanel {

Back in ColorPanel
class

JFrame

1. Create top-level class that


contains a JFrame

Call method
addChangeListener on
each slider, passing in a
new instance of
SliderListener

2. Write a subclass of JPanel that


contains three JSliders, add an
instance of it to the JFrame
3. Write a ChangeListener that
changes a JPanels color based
on value of a JSlider
4. Add ChangeListeners to the
JSliders

JPanel

JSlider
73
of 95
80/106

The Whole App (1/2)

Pass in ColorPanel,
appropriate channel
number and slider as
arguments to each
SliderListener

public ColorPanel() {
Dimension panelSize = new Dimension(300, 150);
this.setPreferredSize(panelSize);
this.setBackground(Color.GRAY);
JSlider sliderRed = new JSlider(0, 255);
JSlider sliderGreen = new JSlider(0, 255);
JSlider sliderBlue = new JSlider(0, 255);
sliderRed.addChangeListener(
new SliderListener(this, 0, sliderRed));
sliderGreen.addChangeListener(
new SliderListener(this, 1, sliderGreen));
sliderBlue.addChangeListener(
new SliderListener(this, 2, sliderBlue));
this.add(sliderRed);
this.add(sliderGreen);
this.add(sliderBlue);
}
74
of 95
81/106

The Whole App (2/2)


public class ColorPanel extends JPanel {

public class ColorPanelApp {

public ColorPanel() {
Dimension panelSize = new Dimension(300, 150);
this.setPreferredSize(panelSize);
this.setBackground(Color.GRAY);
JSlider sliderRed = new JSlider(0, 255);
JSlider sliderGreen = new JSlider(0, 255);
JSlider sliderBlue = new JSlider(0, 255);

public ColorPanelApp() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
ColorPanel panel = new ColorPanel();
frame.add(panel);

sliderRed.addChangeListener(
new SliderListener(this, 0, sliderRed));
sliderGreen.addChangeListener(
new SliderListener(this, 1, sliderGreen));
sliderBlue.addChangeListener(
new SliderListener(this, 2, sliderBlue));

frame.pack();
frame.setVisible(true);

public static void main(String[] args) {


new ColorPanelApp();
}

this.add(sliderRed);
this.add(sliderGreen);
this.add(sliderBlue);

public class SliderListener


implements ChangeListener {
private JPanel _panel;
private int _channel;
public SliderListener(JPanel panel, int channel){
_panel = panel;
_channel = channel;
}

75
of 95
82/106

@Override
public void stateChanged(ChangeEvent e) {
int val = _slider.getValue();
Color bg = _panel.getBackground();
Color newbg;
switch(_channel){
case 0:
newbg = new Color(val, bg.getGreen(),
bg.getBlue());
break;
case 1:
newbg = new Color(bg.getRed(), val,
bg.getBlue());
break;
default:
newbg = new Color(bg.getRed(), bg.getGreen(),
val);
}
_panel.setBackground(newbg);
}

76
of 95
83/106

21

10/9/2014

Putting It All Together: ColorPanelApp

Buttons in Swing

ColorPanelApp

JFrame

Some buttons in Swing:


javax.swing.JButton
javax.swing.JToggleButton
javax.swing.JCheckBox
javax.swing.JRadioButton

ColorPanel

JSlider

SliderListener

77
of 95
84/106

78
of 95
85/106

ButtonGroups

Buttons in Swing

How do we make options mutually exclusive


(i.e. you can only click one button at a time)?
o
o

put them in a button group


javax.swing.ButtonGroup

Buttons that can be added to ButtonGroup:


JRadioButton
JToggleButton
JMenuItem (for advanced users)

79
of 95
86/106

80
of 95
87/106

22

10/9/2014

Modified ColorTextApp: RadioColorListener

JRadioButtons & ButtonGroups


How to use a ButtonGroup:
o

public class RadioColorListener implements ActionListener {


private JLabel _label;
private Color _currentColor
public RadioColorListener(JLabel label, Color color) {
_label = label;
_currentColor = color;
}
@Override
public void actionPerformed(ActionEvent e) {
_label.setForeground(_currentColor);
}
}

create buttons

JRadioButton rB1 = new JRadioButton(Green, not Red);


JRadioButton rB2 = new JRadioButton(Red, not Green);

create ButtonGroup

ButtonGroup bGroup = new ButtonGroup();

add buttons to ButtonGroup


bGroup.add(rB1);
bGroup.add(rB2);

81
of 95
88/106

82
of 95
89/106

Modified ColorTextApp: ColorTextPanel


public class ColorTextPanel extends JPanel {
public ColorTextPanel() {
JLabel label = new JLabel("CS15 Rocks!");
Assume all the swing
JRadioButton buttonForRed = new JRadioButton("Red");
components are
JRadioButton buttonForGreen = new JRadioButton(Green);
imported!
RadioColorListener redListener = new RadioColorListener(label, Color.RED);
RadioColorListener greenListener = new RadioColorListener(label, Color.GREEN);
//add listeners to their buttons
buttonForRed.addActionListener(redListener);
buttonForGreen.addActionListener(greenListener);
//create button group and add buttons to it
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(buttonForRed);
buttonGroup.add(buttonForGreen);
Dimension panelSize = new Dimension(300, 100);
this.setPreferredSize(panelSize);

More Complicated Swing Apps


The examples weve seen so far have been small and
simple
What if we want to construct a more realistic GUI?

For more complex projects


you might want to give the
Buttons a separate JPanel
and use LayoutManagers
(stay tuned!)

We can use LayoutManagers to arrange components


nicely within JPanels

//add label and buttons to ColorTextPanel


this.add(label);
this.add(buttonForRed);
this.add(buttonForGreen);

83
of 95
90/106

84
of 95
91/106

23

10/9/2014

FlowLayout

Using java.awt.LayoutManagers
Each JPanel contains a LayoutManager to
automatically arrange its sub-components

Default layout used by


all JPanels

LayoutManager interface implemented by classes:


o

java.awt.FlowLayout

java.awt.GridLayout

java.awt.BorderLayout

Arranges components
from left to right, top to
bottom

To specify the LayoutManager for a JPanel, either


pass an instance of one of these classes to the panels
constructor or to its setLayout method later
85
of 95
92/106

FlowLayout

86
of 95
93/106

GridLayout

public class FlowTest extends JFrame {


public FlowTest() {
super();
this.setSize(200, 300);
JButton b1 = new JButton(One);
JButton b2 = new JButton(Two);
JButton b3 = new JButton(Tree);
JButton b4 = new JButton(Four);
JButton b5 = new JButton(Five);
JButton b6 = new JButton(Six);
JPanel mainPanel = new JPanel();

When it reaches the


edge of the panel,
moves to next row

FlowLayout fl = new Flowlayout();


mainPanel.setLayout(fl);
mainPanel.add(b1);
mainPanel.add(b2);
mainPanel.add(b3);
mainPanel.add(b4);
mainPanel.add(b5);
mainPanel.add(b6);
this.add(mainPanel);
this.pack();
this.setVisible(true);

87
of 95
94/106

Arranges components in
a grid
Add components left to
right, top to bottom
Must specify grid size in
constructor-- number of
rows and columns
Each cell in grid is same
size, determined by
largest element in grid

95
of 95
95/106

24

10/9/2014

BorderLayout

GridLayout
p1.setBackground(Color.GREEN);
p2.setBackground(Color.RED);
p3.setBackground(Color.ORANGE);
p4.setBackground(Color.CYAN);
p5.setBackground(Color.BLUE);
p6.setBackground(Color.YELLOW);

public class GridTest extends JFrame {


public GridTest() {
super();
this.setSize(200, 300);
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel();
JPanel p4 = new JPanel();
JPanel p5 = new JPanel();
JPanel p6 = new JPanel();
JPanel mainPanel = new JPanel();

GridLayout gl = new GridLayout(3, 2);


mainPanel.setLayout(gl);
mainPanel.add(p1);
mainPanel.add(p2);
mainPanel.add(p3);
mainPanel.add(p4);
mainPanel.add(p5);
mainPanel.add(p6);
this.add(mainPanel);
this.pack();
this.setVisible(true);
89
of 95
96/106

Splits JPanel into 5


regions: NORTH, SOUTH,
EAST, WEST, CENTER
o

These are all static


constants

Must specify region when


adding component to its
container
90
of 95
97/106

BorderLayout

BorderLayout

p1.setBackground(Color.RED);
p2.setBackground(Color.GREEN);
p3.setBackground(Color.ORANGE);
p4.setBackground(Color.CYAN);
p5.setBackground(Color.BLUE);

public class BorderTest extends JFrame {

Dont have to fill all


regions-- default size of a
region is (0, 0)

public BorderTest() {
super();
this.setSize(300, 200);
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel();
JPanel p4 = new JPanel();
JPanel p5 = new JPanel();
JPanel mainPanel = new JPanel();

BorderLayout will adjust


dynamically depending
on what has been added
Typically add to CENTER
first-- it should be largest
91
of 95
98/106

BorderLayout bl = new BorderLayout();


mainPanel.setLayout(bl);
mainPanel.add(p1, BorderLayout.CENTER);
mainPanel.add(p2, BorderLayout.NORTH);
mainPanel.add(p3, BorderLayout.SOUTH);
mainPanel.add(p4, BorderLayout.EAST);
mainPanel.add(p5, BorderLayout.WEST);
this.add(mainPanel);
this.pack();
this.setVisible(true);
92
of 95
99/106

25

10/9/2014

LayoutManagers

LayoutManagers

Youll be using layouts a lot in


CS15-- practice playing around
with them!
Try taking the previous example
and calling setPreferredSize
on each sub-panel to change
their sizes and shapes
If you want to test your
understanding (and want to get
a headstart on Cartoon), try
making something like this:
94
of 95
101/106

93
of 95
100/106

Swing: Summary

Announcements

Swing has a variety of tools to help you make


GUIs:

On-time Due Date for TASafeHouse is Friday,


October 3rd, at 10:00 PM

o
o
o

JFrames, JPanels, JButtons, and JSliders, arranged using


LayoutManagers
ActionListeners and ChangeListeners to respond to user input
Timers to perform a task at regular intervals

Late Due Date for TASafeHouse is Sunday,


October 5th, at 11:59 PM

On future projects, instead of relying on support


code for graphical elements, you will use these
tools yourself!
95
of 95
102/106

26

Potrebbero piacerti anche