Title: Chapter 11: Visual Programming
1Chapter 11 Visual Programming
- In chapters 11 and 12 we study how to build GUI
components for Java programs
- We have already seen JOptionPane
- We will now make our own tailor-made components
which not only permit input, but react when the
user performs an operation
- The operation is known as an event
- We will now build event-driven programs
- While this can be a pretty cool thing to learn,
it involves a lot of code, so the trade-off is
that it will be quite an effort to do even some
simple things with GUIs - We will look at one particular approach to
building event-driven programs, but as with
anything in Java, there are multiple ways to do
this the book mentions two or three ways, but
we will stick with what is the easiest
2Generic GUI Objects
- All GUI components are Objects in Java
- See tables 11.1, 11.2
- note there are usually two types of each
component, the AWT version (which is from an
older version of Java) and the swing version
- We will use the swing versions of each because
they are generally better (because they are newer)
- There are three types of GUI Objects
- Top-level containers
- These components allow us to display GUIs on the
screen, all other GUI components get placed
inside of one of these
- Top-level containers are JFrame, JApplet, JDialog
or JWindow, for our purposes we will only use
JFrames
- Intermediate containers
- These components are used to position atomic
components and are necessary unless we want our
GUIs to have no formatting
- We will only use the JPanel
- Atomic Components
- These are the individual objects that make up the
GUI, or these are the visible components that we
interact with
- JButton, JMenu, JLabel, JCheckBox, JRadioButton,
JTextField, JTextArea
3JFrames
- Our basic container will be a JFrame
- The JFrame will comprise
- a root pane which we do not have to do anything
with
- a content pane to which we will add all of the
intermediate and atomic components
- and optionally a menu bar
- Components are added to the content pane (and to
intermediate containers) based on the layout
selected
Each type of object has a default
layout if we do not decide to select
an alternate layout see table 11.4
4Layouts and Atomic Components
- There are 6 layouts available in Java (see table
11.3), we will use 3 of these
- FlowLayout add as many components as will fit
to this row, start a new row when necessary
- BorderLayout there are 5 regions, North, South,
West, East, Center, for 5 components
- GridLayout designate the number of rows and
columns and add components in order row by row
- There are 7 atomic components (see table 11.5),
we will use 5
- JButton a button on the JFrame that, when
clicked, should cause an action
- JLabel to output text or an image to some area
of the Jframe
- JTextField to input text (String) information
- JCheckBox to offer a group of choices from
which the user can select any or all of, each box
can be checked or unchecked
- JRadioButton to offer a group of choices from
which the user selects exactly 1
5Defining A GUI Component
- There are multiple ways to do this, we will do
the simplest
- Import javax.swing., also java.awt. and
java.awt.event. if necessary
- Your class should add extends JFrame to the
class header
- Create a private data instance of type JFrame
- In your constructor
- instantiate the JFrame
- set the size of the JFrame
- show the JFrame
- Either in your constructor or elsewhere in your
class, add components as necessary to the JFrame
and add listeners if necessary
6Defining A Simple JFrame
import javax.swing. import java.awt.
// needed for BorderLayout
public class AnExample extends JFrame
private JFrame theFrame public
AnExample( ) theFrame new
JFrame("Simple Example Frame")
theFrame.setSize(200, 200)
JPanel aPanel new JPanel( )
aPanel.setLayout(new BorderLayout(
)) JButton b1 new JButton("Button
1") JButton b2 new JButton("Button
2") aPanel.add(b1, BorderLayout.NOR
TH) aPanel.add(b2, BorderLayout.SOUT
H) theFrame.getContentPane( ).add(aP
anel) theFrame.show( )
- Here, we define a simple Jframe which consists of
itself, an intermediate component (a JPanel) and
the JPanel consists of two JButtons
- Below is the GUI this code creates
7Three Problems with AnExample
- First, because this is a class, separate from a
main method, we must import AnExample to another
class and create an instance of AnExample
- We could make AnExample contain a main method,
but it is better to to have this as a separate
class so that none of its components are forced
to be static - There is no windowClosing listener
- Without such a listener (event handler), we can
close the window by clicking on the X box, but it
leaves the program running, we will next learn
how to add a windowClosing listener - The two JButtons do nothing
- Again, this is because these components do not
have listeners, we will add them shortly
8Events and Event Handlers
- Most GUI components, when operated on, generate
an Event
- An Event is an object
- The Event object is handled by a piece of code
called an Event Handler
- If you do not add an Event Handler to your
object, the Event is ignored
- So, for every Event that our object might
generate, if we want it handled, we need to add
code to handle it
- All JFrames can generate a windowClosing event,
so we want to add a windowClosing listener
(handler)
- There are multiple ways to handle this, again we
will take the easiest
9Add a windowClosing Handler
- A windowClosing event generates a call to the
method windowClosing( )
- We must implement windowClosing( ) in our class
- However, we must also add a WindowListener to our
class
- As stated earlier, there are multiple ways to do
this
- We could write a separate WindowListener class
that extends WindowAdapter (the class that is
called upon to close a window)
- We could add a nested inner class that extends
WindowAdapter
- We could define an anonymous class inside our
addWindowListener instruction (this is easiest,
so we will do this!)
- import java.awt.event. which includes the
WindowClosing event object
- Add the instruction theFrame.addWindowListener()
- Inside of the parentheses, include the new class
definition (see next slide)
10Our Modified Class
import javax.swing. import java.awt. impo
rt java.awt.event. public class AnExample exte
nds JFrame private JFrame theFrame
public AnExample( ) th
eFrame new JFrame("Simple Example Frame")
theFrame.setSize(200, 200)
JPanel aPanel new JPanel( )
aPanel.setLayout(new BorderLayout(
)) JButton b1 new JButton("Button
1") JButton b2 new JButton("Button
2") aPanel.add(b1, BorderLayout.NOR
TH) aPanel.add(b2, BorderLayout.SOUT
H) theFrame.getContentPane( ).add(aP
anel) theFrame.show( )
theFrame.addWindowListener(new WindowAdapter( )
public void windowClos
ing(WindowEvent ev)
System.exit(0) )
- Added instructions are in italics
- Notice the syntax for the new WindowAdapter
object this is inside of a parameter passed to
addWindowListener, so you must be careful when
you end the parameter list - Note there are other window events we could
similarly implement such as windowIconified,
windowDeiconified, but we wont bother with those
- see table 11.7 for other Window events
11Adding JButton Event Handlers
- Like the WindowClosing handler, there are many
ways to add a JButton event handler
- However, whereas the WindowClosing handler has a
single task to perform (System.exit(0)), we might
want each JButton to do something different, and
each task might be complex - So, we will find an alternative approach to
adding JButton handlers
- Two possibilities are to define an inner class
that implements the handlers or to define a
separate class and import it
- Since our button handler code will probably be
tailored for this specific class, we will use the
inner class approach
12Defining an Inner Class
- Defining an Inner Class is like defining any
class
- We have a class definition
- private class InnerClassName implements
ActionListener
- Note that since this InnerClass is only going to
be used inside of our current class, we make it
private instead of public (the book omits the
word private in their examples, but it is more
proper to include private, if it is omitted, it
defaults to private) - This class will implement the JButton listener
which is called an ActionListener, so we must add
implements ActionListener
- The class will consist of a single method called
actionPerformed(ActionEvent ev)
- ev is a parameter, you can call it whatever you
want but it must be included
- The actionPerformed method will include the code
to handle whatever you want your GUI to do
whenever one of the JButtons is pressed
13Adding the ActionListener
- Now that you have an InnerClass that implements
the actionPerformed method, you have an
ActionListener class
- But, the ActionListener must now be attached to
the items that need listening
- So, add this class as the ActionListener for each
of your JButtons
- You can do this by either
- b1.addActionListener(new InnerClassName( ))
- Or by
- InnerClassName foo new InnerClassName( )
- b1.addActionListener(foo)
- And of course, the same thing for your other
button
14Divergence implements
- What does implements ActionListener mean?
- Java includes a type of class called an abstract
class
- This type of class is one that is only partially
implemented
- Other Java classes know to call upon methods of
this class, but the methods are only defined as
abstract, so someone else has to actually
implement them - When you say implements ActionListener, you are
telling Java that your class will implement the
necessary methods (in ActionListener, there is
only one method needed, actionPerformed) - In this way, if a class has a JButton that is
pressed, then your class that implements
ActionListener can handle the ActionEvent that is
generated when the JButton is pressed - Table 11.7 shows some of the Events and abstract
classes available for GUI components, some of
these will be necessary, others will not
depending on what we want our particular GUI to
handle
15Implementing actionPerformed
- Your actionPerformed method will be called
whenever any JButton is pressed
- How do you know which button was pressed?
- The actionPerformed method is passed an
ActionEvent which includes the String from the
JButton
- To obtain this string, do ev.getActionCommand(
)
- Now, your actionPerformed method can use nested
if-else statements so that, you compare each
JButton String against the String obtained from
ev, and perform the appropriate action
16Complete Example
- Lets put together everything weve now learned
to build a GUI counter as follows
- The class will keep track of an int variable
counter and use a GUI to permit user input
- There will be five buttons, increment, decrement,
increment by 5, decrement by 5, and clear (this
will reset the counter to 0, the others will
alter counter as you would expect) - We will need to add the 5 buttons to the JFrame,
we will use BorderLayout for this
- We will add an ActionListener to each of the 5
buttons and implement an actionPerformed method
which will determine which button was pressed and
then take the appopriate action on counter and
output the new counter value to the console
window (System.out) - We will add a windowClosing listener
17The Code
fr.addWindowListener(new
WindowAdapter() publi
c void windowClosing(WindowEvent ev)
System.exit(0)
)
private class InnerClassName implements
ActionListener public void
actionPerformed(ActionEvent ev)
String temp ev.getAction
Command() if(temp.equals("Increment"))
counter counter
System.out.println(counter)
else if(temp.equals("Increment by 5"))
counter5 System.out.println(
counter) else if(temp.equals("Clear Counter"
)) counter0 System.out.prin
tln(counter) else if(temp.equals("Decr
ement by 5")) counter-5 Sy
stem.out.println(counter) else if(temp.equal
s("Decrement")) counter-- S
ystem.out.println(counter)
import javax.swing. import java.awt. impo
rt java.awt.event. public class GUICounter ext
ends JFrame private JFrame fr
private int counter public GUICounter( )
counter 0 fr new
JFrame("GUI Counter") fr.setSize(400
, 100) JPanel panel new JPanel( )
panel.setLayout(new BorderLayout( ))
JButton inc new JButton("Incremen
t") JButton inc5 new JButton("Incr
ement by 5") JButton clear new JBu
tton("Clear Counter") JButton dec5
new JButton("Decrement by 5")
JButton dec new JButton("Decrement")
inc.addActionListener(new InnerClas
sName( )) inc5.addActionListener(new
InnerClassName( )) clear.addActionL
istener(new InnerClassName( ))
dec5.addActionListener(new
InnerClassName( )) dec.addActionList
ener(new InnerClassName( )) panel.add
(inc, BorderLayout.NORTH) panel.add(
inc5, BorderLayout.WEST) panel.add(c
lear, BorderLayout.CENTER) panel.add
(dec5, BorderLayout.EAST) panel.add(
dec, BorderLayout.SOUTH) fr.getConten
tPane( ).add(panel) fr.show( )
18Common Errors
- Forgetting to import the proper library
- javax.swing. for the components
- java.awt. for the layout manager(s)
- java.awt.event. for event handlers
- Forgetting to add your atomic components to an
intermediate component and/or forgetting to add
your intermediate component(s) to your JFrame
- Use add for adding to your intermediate
components and getContentPane( ).add for your
JFrame
- Forgetting to implement an ActionListener for
your atomic components, forgetting to implement
actionPerformed in your inner class, or
forgetting to add your ActionListener inner class
to your atomic components