Introducing The Basics of Guis and Event-Handling in Java

Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 51

Aris Papadopoulos

ap7@doc.ic.ac.uk

Event Handling in Java TM

Introducing the
basics of GUIs and
event-handling in
Java
GUI components
• Buttons
Common
buttons
Radio
buttons
Check
buttons
GUI components
• Combo
boxes
• Lists
• Menus
GUI components
• Spinners
• Sliders
• Textfields
Console vs. GUI applications
• What is the difference between
a GUI and a console app?

• From the programmer’s perspective?

• A console app enables interaction through a specified


“flow” of I/Os. A GUI app makes it much more flexible. The
user is allowed to perform combinations of actions. The
programmer must have taken all possible behaviors in mind.
Console vs. GUI applications

• The app controls the type and order of the


interactions
GUI classes
• Components you use to build
a GUI app, are instances of
classes contained in the
javax.swing package:
– JButton
– JTextField
– JRadioButton
– JCheckBox
– JComboBox
– JLabel etc…
Building GUIs essentials
• A GUI consists of a number of
components contained in some
pane.
• To appear onscreen, every GUI
component must be part of a
containment hierarchy. A
containment hierarchy is a tree of
components that has a top-level
container as its root.
• For Java apps this top-level
container will typically be a
JFrame.
• Components will then be “pinned”
on the top-level container’s
content pane.
Building GUIs essentials

JFrame
object Container JButton object
object
JLabel object
Building GUIs essentials

• Putting this in code:


import javax.swing.*;
public class MyApp extends JFrame{
private JButton b1;
private JLabel l1;
Public MyApp(){
super(“SwingApplication");
Container myCont = getContentPane();
b1=new JButton(“I’m a Swing button!”);
l1= new JLabel(“Number of button clicks: “ + num);
myCont.add(b1);
myCont.add(l1);
}
GUI components again…
• JButton:
– JButton(Icon i)
– JButton(String s)
– JButton(Icon i, String s)
• JTextField:
– JTextField()
– JTextField(int cols)
– JTextField(String s, int
cols)
– JTextField(String s)
…and again…
• JList:
– JList()
– JList(Vector v)
– Example:
String[] data = {"one", "two",
"three", "four"};
JList dataList = new JList(data);
dataList.add(“five”);
…and again
• JRadioButton:
– JRadioButton(String s, Icon i,
boolean state)

– Example:
JRadioButton rb1= new
JRadioButton(“one”);
JRadioButton rb2= new
JRadioButton(“two”);
ButtonGroup bg= new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
Layout Managers
• You use layout managers
to design your GUIs.
• There are several
managers like:
– FlowLayout
– BorderLayout
– GridLayout
– CardLayout
– GridBagLayout
FlowLayout
• Default layout
• Components laid out from
the top-left corner, from
left to right and top to
bottom like a text.
BorderLayout

• Places components in up to five areas:


top, bottom, left, right, and center. All
extra space is placed in the center area
GridLayout

• Simply makes a bunch of components


equal in size and displays them in the
requested number of rows and columns
CardLayout

• lets you implement an


area that contains
different components
at different times. A
CardLayout is often
controlled by a combo
box, with the state of
the combo box
determining which
panel (group of
components) the
CardLayout displays
GridBagLayout

• is a sophisticated, flexible layout


manager. It aligns components by placing
them within a grid of cells, allowing some
components to span more than one cell.
Layout Managers
• Putting it into code:
– Setting the manager:
Container myCont =
getContentPane();
myCont.setLayout(new FlowLayout());

– Adding Components:
myCont.add(aComponent, BorderLayout.WEST);
The delegation model
• Sources:
– The mouse and keyboard and
the GUI components (Buttons,
lists, checkboxes etc.)
• Events:
– Objects that describe a state
change in a source.
• Listeners:
– Objects notified when events
occur.
The delegation model

Event
Object
Event Listener
Source

1st part of this


presentation

The Source
When
Thethe generates
Source
state of thean
registers event
source
a
and sends
changes… it to the registered
Listener…
listener
Listeners
• Any number of event listener
objects can listen for all kinds
of events from any number of
event source objects.
• E.g. a program might create
one listener per event source.
• Or a program might have a
single listener for all events
from all sources.
Listeners
• Multiple listeners can
register to be notified of
events of a particular type
from a particular source.
• Also, the same listener
can listen to notifications
from different objects.
Listeners
• Each type of listeners can
be notified only for its
corresponding types of
events which can be
generated by specific
types of sources.
Multiple sources, single listener
• Many buttons can register
the same listener since all
buttons generate the same
type of event. This type of
event may be generated by
other types of sources as
ActionListener
well. Act io nEv ent1
n t2
e
button1 n Ev
tio
Ac

t3
button2 en
v
nE
io
t
Ac

ListItem3
Single source, multiple listeners

• A single source may


generate different types
of events and thus
register multiple
listeners.
MouseWheel MouseWheelEvent
Listener

nt
MouseEve
MouseMotion
Listener
Listeners as interfaces
• You implement an interface
to create a listener.
• In the case of a single source
that generates multiple types
of events you can create a
single listener that
implements all interfaces
(remember: a class may
extend only one superclass
but implement more than one
interfaces).
Single source, multiple listeners again

MouseWheel MouseWheelEvent
MouseWheel +
Listener
MouseMotion
Listener
nt
MouseEve
MouseMotion
Listener
Sources-events-listeners
Source Event Listener Methods
(argument:
<state change> corresponding event)

Mouse MouseEvent MouseListener mouseClicked


<mouse clicked, pressed, mousePressed
dragged, moved/ entered, mouseReleased etc
exited a component etc>
MouseMotionListener mouseDragged
mouseMoved

MouseWheelEvent MouseWheelListener mouseWheelMoved


<page-up and down>

Keyboard KeyEvent KeyListener keyPressed


keyReleased
keyTyped
Sources-events-listeners
Source Event Listener Methods
(argument:
<state change> corresponding event)

Button ActionEvent ActionListener ActionPerformed


<GUI button clicked>

List ActionEvent ActionListener ActionPerformed


<item double clicked>
ItemEvent ItemListener ItemStateChange
<item selected/deselected>
d
Event handling steps
• To handle an event you
need 3 steps:
– Implement the appropriate
interface that will produce
your listener class.
– Create a listener object.
– Register the listener to the
source of interest.
Putting it into code
• You register a listener
using the corresponding
add function in the form:
component.addSomeListener(listener_object);

• You can find the source


of an event by using the
getSource method:
event_object.getSource();
Putting everything together
• So you need two classes:
– The one that extends
JFrame (see part one)
which will create your GUI
and
– The one(s) that will
implement your listener(s).
– Or one that does them
both!
Inner classes
• You may create all different
classes independently and
put them in separate files,
or…
• you can implement your
listeners inside the class that
extends your JFrame, making
it an inner class.
• This enables you to put
everything in one class (and
hence file).
Adapter classes
• Adapter classes are fully abstract
classes that correspond to listener
interfaces. They are extended (not
implemented) and thus you can ignore
methods that do not interest you. You
can use them instead of listeners in the
case that only some of the methods of
the interface are to be used. You don’t
use the abstract specifier and of course
you cannot use multiple inheritence.
• Some adapter classes:
– KeyAdapter (instead of KeyListener)
– MouseAdapter (MouseListener)
– MouseMotionAdapter
(MouseMotionListener) etc…
Create your window (1/2)

//Extend a JFrame:
public class MyApp extends JFrame{ ...

//Declare all your components private:


private JButton b1, ...;

//Create your constructor:


Public MyApp(){
super(“SwingApplication");...

//Inside your constructor:


//Get your container:
Container myCont = getContentPane();
Create your window (2/2)
//Inside your constructor, set a layout:
GridBagLayout layout = new GridBagLayout();
myCont.setLayout(layout);

// Inside your constructor, create your element objects:


b1=new JButton(“I’m a Swing button!”); ...
// Inside your constructor, Add them on your content pane:
myCont.add(b1); ...
// Inside your application class, add the main method that is the entry point of your program and creates the application object:
public static void main(String[] args){
MyApp a =new MyApp();
a.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
Event handling in practice (1/2)
• When an event is generated by a source it
is handled by the listener registered by this
source.
• As shown, the listener is an implemented
interface (or an extended adapter) and thus
you have to implement some methods.
• These methods take the event as an
argument and this is where you put the
code to be executed when the event
happens.
• In other words, you define what you want
to happen eg. when a button is pressed,
inside the actionPerformed method
implemented inside the listener (also see
the tables presented in part-2).
• To be able to do that efficiently, the event
classes define specific methods to extract
information about the events.
Event handling in practice (2/2)
• EventObject:
// superclass of all events, so the following
method is inherited by all event objects
– Object getSource()
• MouseEvent:
– int getX(), int getY()
– int getButton()
• KeyEvent:
– char getKeyChar()
• ActionEvent:
– String getActionCommand()
– long getWhen()
//This adds to the tables presented in part-2.
Four design options
• Implement your handlers:
– in separate classes,
– using inner classes
– using anonymous inner
classes,
– in the same class that creates
your window.

• You put everything


together according to your
choice.
Using inner classes (1/2)
• This is the easiest and
more practical approach.
• Inner classes belong to
the app class and have
access to all its members.
• The only thing you have
to do is implement the
handler and add its object
to the element.
Using inner classes (2/2)
//Declare your handler class:
class MyHandler Implements ActionListener{ ...
//Add the actionPerformed method inside your handler class:
public void actionPerformed(ActionEvent ev){...

// Inside your app’s constructor, create your element objects:


b1=new JButton(“I’m a Swing button!”); ...
// Inside your app’ s constructor, add them on your content pane:
myCont.add(b1); ...
// Tie them together in two steps:
// Create a handler object inside the app’s constructor:
MyHandler handler = new MyHandler();
// Add it to the element:
b1.addActionListener(handler);
Using anonymous inner classes
(1/2)
• This is a variation of the
previous option.
• An anonymous inner
class is an inner class
without a name.
• You define the class “on
the fly” when you need an
instance of it (an object)
to be created.
Using anonymous inner classes
(2/2)
//Inside the app’s constructor where you have added the component on the content pane, add the listener just as in the previous case. Only this
time write its code at the same time you instantiate and add it:

b1.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent ev) {...


Using a separate class (1/4)
• Since this does not
belong to the app class, it
cannot access its private
members directly.
• Due to the above you
need to implement public
access methods for each
app’s element in order to
be able to interact with
them through the handler.
Using a separate class (2/4)
• Apart from the above you
need to pass a reference of
your app object to the
handler in order to tie the app
and the handler together.
• Using an inner class you
didn’t have to do this, since
the handler class belong to
the app itself.
• How you do this:
Using a separate class (3/4)
// Create a handler object inside the app’s constructor. Pass a reference to the app using this as an argument:
MyHandler handler = new MyHandler(this);
// Add it to the element (as with the inner classes):
b1.addActionListener(handler);

// Inside the handler class:


// Declare an app object:
MyApp appObj;
// Create a handler’s constructor which takes an app object as an argument. This is the app object that ties the app with the handler. Assign this object to the object declared inside your handler’s class.
public MyHandler (MyApp app){
appObj=app;
}
Using a separate class (4/4)
// Inside the handler class:
// Add the actionPerformed method (as previously) and access all elements through the appObj:
public void actionPerformed(ActionEvent ev)
{
if ev.getSource()==appObJ.b1{...
...

• Play around! What would happen if:


– You construct a new app object inside the handler class?
– You construct it inside the actionPerformed method?
Using the same class (1/2)
• You can make the class
that extends a JFrame
(the app class) to listen to
its own events. This way
you have all access
advantages you had by
using inner classes and
putting everything
together is easy as well.
Using the same class (2/2)
//Extend a JFrame and implement a handler at the
same time. actionPerformed is now a method of
this same class:
class MyHandler extends JFrame implements
ActionListener{ ...
//Inside the app’s constructor, register the listener by
using this, as the handler-adding methods need
handler objects to be passed as arguments. In this
case the object passed is of the very same class:
b1.addActionListener(this);

You might also like