Simple user interfaces

skatechildrenSoftware and s/w Development

Nov 3, 2013 (3 years and 7 months ago)

61 views

Simple user interfaces

Liang, Chapter 10 (some parts)

Liang Chapter 11 (some parts)


Jframes

: user interfaces

Next we’re going to learn how to get java to create more
complicated
JFrames

for input and output. These can contain
larger text areas, multiple buttons, choice buttons, graphics, etc.

These are a type of GUI (Graphical User Interface).

In describing
Jframes
I’m going to use sections of Liang chapter
10 and chapter 11. I’ll skip bits of these chapters, though.

Parts of a
JFrame

This is a

Jframe
. It is a
window with various user
interface components.

Every
JFrame

contains a
contentPane
, which is a
Container

holding all of the
contents of the
JFrame

The

contentPane
may contain

JPanels
,
with each panel
containing a subgroup of
JComponents
.

A
Jpanel

containing two
JButtons

and two
JCheckBoxs

Test frame

_

_

submit

clear

male

female

This is a text area

with multiple lines

in it


The

contentPane
can
hold

JComponents

such as
JMenu,
JTextArea,
JCheckBox,
JRadioButton,
JButton

etc..

Example Jframe
(see Liang 10.3.1)

import javax.swing.*; // JFrame is a swing class


public class MyFrame{


public static void main(String[] args){


JFrame frame = new JFrame(
"
my first JFrame
"
);


frame.setSize(400,300); // size of frame in pixels


frame.setVisible(true); // make the frame appear


// on the screen


frame.setDefaultCloseOperation(JFrame.
EXIT_ON_CLOSE
);


}

}

There’s no

System.exit()
here. Instead, this line tells the MyFrame
program to exit when the frame window is closed by the user. You just have to
include this to get the program to end properly.

This program does nothing but display an empty
Jframe
.

Screen coordinates go from upper
left corner.

(0,0)

(600,0)

(0,400)

(600,400)

X

Y

Placing a
JFrame

at a location

import javax.swing.*; //
JFrame is a swing class


public class MyFrame{


public static void main(String[] args){


JFrame frame = new JFrame(
"
my first JFrame
"
);


frame.setSize(400,300); //
size of frame in pixels


frame.setLocation(300,300);

//
location of upper
-
left corner


//
of frame on screen (in pixels)


frame.setVisible(true); //
make the frame appear


frame.setDefaultCloseOperation(JFrame.
EXIT_ON_CLOSE
);


}

}

Liang 10.3.1 gives code for getting the size of the screen and using
setLocation to place the frame in the center of the screen.

(Click
here
to download this program)

JFrame

with a component
(10.3.3)


To add an interface component to a frame (like a
JRadioButton
, a
JButton
, a
JTextArea
,etc), we have to get the
ContentPane

of the frame and add the
component to that
ContentPane
.



A
ContentPane

is a
Container
. We can add a component using the
Container

class, like this:


Jbutton myButton = new JButton(
"
hello!
"
);


Container content = frame.getContentPane();


content.add(myButton);


Or, more compressed:


Container content = frame.getContentPane();


content.add(new JButton(
"
hello!
"
));


Or even more compressed:


frame.getContentPane().add(new JButton.(
"
hello!
"
));




Container

is a class from the package java.awt.*. We have to
import
java.awt.*

to use
Container

.


JFrame

with a component
(10.3.3)

import javax.swing.*; // JFrame is a swing class

import java.awt.*; // awt to use the Container class


// it’s ‘java’ not ‘javax’!


public class MyFrame{


public static void main(String[] args){


JFrame frame = new JFrame(
"
my first JFrame
"
);


frame.setSize(400,300);


Container content = frame.getContentPane();


content.add(new JButton(
"
hello!
"
));


frame.setVisible(true);


frame.setDefaultCloseOperation(JFrame.
EXIT_ON_CLOSE
);


}

}

This creates a frame with a single big button in it, saying “hello!”

A
JCheckBox

component
(download
here
)

import javax.swing.*; // JFrame is a swing class

import java.awt.*; // to use the Container class


// it’s ‘java’ not ‘javax’!


public class MyJCheckBoxFrame{


public static void main(String[] args){


JFrame frame = new JFrame(
"
my JCheckBox JFrame
"
);


frame.setSize(400,300);


Container content = frame.getContentPane();


content.add(new JCheckBox(
"
check this
"
, true));


frame.setVisible(true);


frame.setDefaultCloseOperation(JFrame.
EXIT_ON_CLOSE
);


}

}

“new JCheckBox(“check this”, true));”
creates a
JCheckBox

with
the box already checked (that’s what the ‘true’ means)

A
JTextArea

component
(liang 11.6)

import javax.swing.*; // JFrame is a swing class

import java.awt.*; // to use the Container class


// it’s ‘java’ not ‘javax’!


public class MyJTextAreaFrame{


public static void main(String[] args){


JFrame frame = new JFrame(
"
my JTextArea JFrame
"
);


frame.setSize(400,300);


Container content = frame.getContentPane();


content.add(new JTextArea(4,25));


frame.setVisible(true);


frame.setDefaultCloseOperation(JFrame.
EXIT_ON_CLOSE
);


}

}

“new JTextArea(4,25));”
creates a
JTextArea

object that is 4
characters (or lines) high and 25 characters across (for the user to type in).

More than one component in a
JFrame
.


The programs we’ve seen so far just put one component into a
JFrame
. We usually want more than one component.


If we have more than one component in a
JFrame
, we have to
organise their layout.


We
set

a
layout manager

object for the
contentPane
.


There are different predefined layout managers:


flowLayout()

places components left to right in the order they were added


gridLayout(int rows, int columns)

defines a grid of rows*columns locations


borderLayout()

has five locations, north south east west center. This is the
default layout manager in
contentPane

objects.



When we add multiple components to the
contentPane
, they are
placed in position by the layout manager we have placed in the
contentPane.

If we put different layout manager objects in, we
will get different layouts.

Creating and setting a LayoutManager

import javax.swing.*;

import java.awt.*;


public class MyFlowFrame{


public static void main(String[] args){


JFrame frame = new JFrame(
"
my flowLayout JFrame
"
);


frame.setSize(400,300);


Container content = frame.getContentPane();


content.setLayout(new FlowLayout());


for(int i=0; i<20; i++){


content.add(new JCheckBox(
"
check " + i));


}


frame.setVisible(true);


frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


}

}

We could use
new
flow
Layout(
5,5)

, which would put 5 pixel spaces between
components,
new
flow
Layout(
FlowLayout.LEFT)

which would align
components to the left, or
new
flow
Layout(
FlowLayout.LEFT,5,5)
to do both

Setting a gridLayout manager
(download
here
)

import javax.swing.*;

import java.awt.*;

public class
M
y
Grid
Frame{


public static void main(String[] args){


JFrame frame = new JFrame("my
gridLayout

JFrame");


frame.setSize(400,300);


Container content = frame.getContentPane();


content.setLayout(
new GridLayout(10,2)
);


for(int i=0; i<20; i++){


content.add(new JCheckBox("check " + i));


}


frame.setVisible(true);


frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


}

}

new GridLayout(10,2
)
creates a layout manager object that puts components in a
grid 10 rows down, 2 columns across. We could use
new GridLayout(10,2
,5,5)
,
which would create a 10 by 2 grid with 5 pixel spaces between components

Playing with LayoutManagers


Experiment with these 3 Layout Managers


For each, observe effects of resizing the window


For each, explore arguments to the constructor


To avoid surprises, always explicitly set a LayoutManager


Expect surprises and trial and error


Notice that things are placed in the layout
according to the
order in which they were added to the

contentPane.
In these examples, I added things using a loop. This is just for
demonstration purposes!

I also added the same thing each time. Again, this is just for
demonstration: you can add any type of

JComponent.

1 JTextArea and 4 JButtons
(download
here
)

import javax.swing.*;

import java.awt.*;

public class MyFourButtonFrame{


public static void main(String[] args){


JFrame frame = new JFrame(
"
my first JFrame
"
);


frame.setSize(400,300);


Container content = frame.getContentPane();


content.setLayout(new BorderLayout());


content.add(new JTextArea(4,25),BorderLayout.CENTER);


content.add(new JButton(
"
North
"
), BorderLayout.NORTH);


content.add(new JButton(
"
South
"
), BorderLayout.SOUTH);


content.add(new JButton(
"
West
"
), BorderLayout.WEST);


content.add(new JButton(
"
East
"
), BorderLayout.EAST);


frame.setVisible(true);


frame.setDefaultCloseOperation(JFrame. EXIT_ON_CLOSE);


}

}

A

BorderLayout Jframe
has 5 specified locations:

BorderLayout.CENTER,NORTH,SOUTH EAST WEST

MyGridFrame

extends
Jframe
(download
here
)

import javax.swing.*;

import java.awt.*;

class
M
y
Grid
Frame

extends JFrame
{


MyGridFrame(
){

// constructor


super
("my
gridLayout

JFrame");

// superclass constructor


Container content =
this
.getContentPane();


content.setLayout(new GridLayout(10,2));


for(int i=0; i<20; i++)


{ content.add(new JCheckBox("check " + i)); }


this
.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


}

}

class testGridFrame{


public static void main(String[] args) {


MyGridFrame frame = new MyGridFrame(); // make a MyGridFrame


frame.setSize(400,300);

// set the size


frame.setVisible(true); // make it visible


}

}



Notice that the

MyGridFrame
object has methods

setSize
and

setVisible:
it inherits them from

JFrame

Liangs
FlowLayout

example (page 386)

import javax.swing.*;

import java.awt.*;

public class ShowFlowLayout extends Jframe{


public ShowFlowLayout(){


Container container = getContentFrame();


container.setLayout(new FlowLayout(FlowLayout.LEFT,10,20);


for (int i = 1; i <= 10; i++){


container.add(new Jbutton(
"
Component
"
+i));


}


}



public static void main(String[] args){


ShowFlowLayout frame = new ShowFlowLayout();


frame.setTitle(
"
show flow layout
"
);


frame.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE);


frame.setSize(400,300);


frame.setVisible(true);


}

}

In this example, the
main

method is inside the

ShowFlowLayout
class, rather than there being a separate test class.

Class
JPanel


Most interfaces combine several kinds of component:


text boxes


messages


check buttons


clickable buttons


menus


graphics


Often we want to group some of these together, for
layout reasons.


Interface components are grouped within
JPanels


JPanel

comes from
javax.swing

Example using JPanel

This is a

Jframe
. It is a
window with various user
interface components.

Every
JFrame

contains a
contentPane
, which is a
Container

holding all of the
contents of the
JFrame

The

contentPane
may contain

JPanels
,
with each panel
containing a subgroup of
JComponents
.

A
Jpanel

containing two
JButtons

and two
JCheckBoxs

Test frame

_

_

submit

clear

male

female

This is a text area

with multiple lines

in it


The

contentPane
contains

JComponents

such as
JMenu,
JTextArea,
JCheckBox,
JRadioButton,
JButton

etc..

import javax.swing.*; //
(download
here
)

import java.awt.*;

class MyFrame extends JFrame{


MyFrame(){


super("JFrame with button and checkbox panel");


JPanel myPanel = new JPanel();

//
create panel


myPanel.setLayout(new GridLayout(0,4));

//
set layout of panel


myPanel.add(new JButton("submit"));

//
add button to panel


myPanel.add(new JButton("clear"));

//
add another button


myPanel.add(new JCheckBox("male", true));

//
add checkbox to panel


myPanel.add(new JCheckBox("female", false));

//
another checkbox


Container content = this.getContentPane();


content.setLayout(new BorderLayout());


content.add(new JTextArea(16,25),BorderLayout.CENTER);


content.add(myPanel,BorderLayout.SOUTH);

//
add panel to frame


this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


}

}

class testMyFrame{


public static void main(String[] args) {


MyFrame frame=

new

MyFrame
();


frame.setSize(300,200);


frame.setVisible(true);


}

}

In this example,
Jframe

has two components: a
JTextArea
, and the
JPanel
, which itself
contains
JButtons

and
JCheckBoxes

Putting messages in
JPanels

(liang 10.6)

The things we’ve put in

JPanels
so far are interface components like

JButtons
and

JCheckBoxes.
How do those things actually get onto the
screen?

Jpanel
has a method called

public void paintComponent(Graphics g)

which is called whenever a

JPanel
object is to be “painted” onto the screen. This
is given a

Graphics
object

g
by the Java system, which represents the bit of
screen where the

JPanel
is to be drawn. Every

JPanel
paints its interface
components onto the screen using this

Graphics
object

g
.

We don’t care what goes on inside the
paintComponent
method. However, if
we want to put messages, or draw pictures, into our
JPanels
, we need to
override

the
paintComponent

method (redefine the method so that it draws what we want
onto the screen). We use methods in
Graphic
object

g

for this:


g.drawString(
“Hello”
,x,y);

//
draws string “hello” at location x, y in the bit of


//
screen represented by

Graphics
object

g


Extending
JPanel

and overriding

paintComponent()

to draw a message on a panel

import javax.swing.*;

import java.awt.*;


class MyMessageJPanel extends JPanel{


String message;

// message contents for panel


int x
location
,y
location
;

// message location in panel




MyMessageJPanel(String msg, int x, int y){

// constructor


super();

// call constructor for superclass
JPanel

first


message = msg;


x
location

= x;


y
location

= y;


}




public void paintComponent(Graphics g){

// override
paintComponent


super.paintComponent(g);



// first do whatever
paintComponent
in
JPanel

always does


g.drawString(message,x
location
,y
location
);


}

// next use the drawString method to draw our message in the
JPanel

}

This

paintComponent
method is called whenever
a

Jpanel
is painted on the screen. We’ve changed it
so it draws our message whenever it’s called.

Using our extended
JMessagePanel

class MyMessageJFrame extends JFrame{


MyMessageJFrame(){

// constructor for
MyMessageJFrame


super("JFrame with MyMessageJPanel");


MyMessageJPanel messagePanel
;


messagePanel

= new

MyMessageJPanel("
Hello world!
",50,50);


//
create a

MyMessageJPanel
object that


//

draws
"
hello world!
"

at location 50, 50


Container content = this.getContentPane();


content.setLayout(new BorderLayout(15,15));


content.add(messagePanel,BorderLayout.CENTER);


this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


}

}


class testMyFrame{

// class to test out these classes


public static void main(String[] args) {


MyMessageJFrame frame= new MyMessageJFrame();


frame.setSize(300,300);


frame.setVisible(true);


}

}


When the
MyMessageJPanel

object is painted on the screen, our overridden

paintComponent
method will draw the message we gave to the constructor.

Noticing events: A Button Click


A JFrame contains a JButton


To respond when the JButton is clicked, we create an actionListener
object to listen for the action of that JButton being clicked.


That actionListener object must contain a method called



public void ActionPerformed(ActionEvent e)


The actionListener object
registers

with the Jbutton.


Thereafter, whenever the JButton is clicked, it calls the
actionPerformed(ActionEvent e) method in the listener.


The actionPerformed
(ActionEvent e)

method does whatever we
want to happen when the button is clicked.

count

myActionListener {


actionPerformed(ActionEvent e){


JOptionPane.showMessageDialog(“Button click!”);


}

}

event e:
Click

Listener registers
with JButton

JOptionPane

Button Clicked!

JButton myCountButton = new JButton(“count");

myCountListener listener = new myCountListener();

myCountButton.addListener(listener);

This snippet of code creates a

JButton
object, then creates a

myCountListener
object, the registers that listener with that button (adds
the listener object as a listener to the button).

This registration step creates the link between the button and the listener: after
this step, when the button is clicked, the
actionPerformed()

method in
the listener object will be executed.

Next: putting it all together.

Registering a listener object with a source
(a Jbutton)

Making the
JFrame

class
implement
ActionListener


Any class at all can implement ActionListener, if it provides the
actionPerformed() method.


Its most useful to make the class that draws our windows (our
JFrames) also implement ActionListener, so that objects from that
clss not only draw buttons but can respond to events on those
buttons.


To do this we change our myButtonJFrame class so that it proves an
actionPerformed() method as well as constructing the JFrame object.


I’ll call this new class EventButtonJFrame

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

//
we need event classes


class
Event
ButtonJFrame extends Jframe

implements ActionListener
{


JTextArea myTextArea = new JTextArea
(
6,30),


JButton myCountButton = new JButton("Count");

// make button


JPanel buttonPanel = new JPanel();


Event
ButtonJFrame (){

//
constructor


super(“
my
ButtonJFrame");


myCountButton.addActionListener(
this
);


//
register this class as the listener


//

for myCountButton


buttonPanel.setLayout(new GridLayout(4,0));


buttonPanel.add(myCountButton);

//
add button to panel


Container content = this.getContentPane();


content.setLayout(new BorderLayout());


content.add(myTextArea,BorderLayout.CENTER);


content.add(buttonPanel, BorderLayout.EAST);


this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


}



public
void actionPerformed(ActionEvent e) {


JOptionPane.showMessageDialog(null,
”Count

button clicked
!
");


}


}


Doing something useful

The

actionPerformed
method in the previous programs doesn’t really do
anything useful.


To get that method to do something useful, we could, for example, give it access
to the

JTextArea
object created in our
JFrame

window.


To do this, we will

1) Make the

JTextArea
object a generally accessible variable in the

Jframe
object. To do this, we put

JTextArea myTextArea = new JTextArea("this is a text area",6,30);

at the top of the

EventButtonJFrame
class definition.

2)
Refer to the text in that

JtextArea
object

in the

actionPerformed

method, so that when our count button is clicked, we can return some useful
information.


We can get the text inside the

JTextArea
object by saying

myTextArea.getText();

(we can change that text by saying something like:

myTextArea.setText(“this is the new text”);

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

//
we need event classes

class EventButtonJFrame extends JFrame implements ActionListener{


JTextArea myTextArea = new JTextArea("this is a text area",6,30);


JButton myCountButton = new JButton("count");

// create button


JPanel buttonPanel = new JPanel();


Event
ButtonJFrame (){


super("myButtonJFrame");


myCountButton.addActionListener(this);

// add listener


buttonPanel.setLayout(new GridLayout(4,0));


buttonPanel.add(myCountButton); // add button


Container content = this.getContentPane();


content.setLayout(new BorderLayout());


content.add(myTextArea,BorderLayout.CENTER);

// add text area


content.add(buttonPanel, BorderLayout.EAST);


this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


}


public void actionPerformed(ActionEvent e) {


JOptionPane.showMessageDialog(null, “
The
number of characters in
JTextArea is "+myTextArea.getText().length() );


}

}

Whenever the count button is clicked, we get a message telling us
how many characters are currently in
myTextArea
.

Download from
here

class test
EventButton
JFrame {


public static void main(String[] args) {


EventButtonJFrame

frame = new
EventButtonJFrame
();


frame.setSize(300,200);


frame.setLocation(300,330);


frame.setVisible(true);




}

}

This program will respond to a click on the count button by popping
up a text message telling the user how many characters are currently
entered in the
JTextArea

of the
EventButtonJFrame

object.

Note that for this program to compile and run properly, it must be in
a file called
testEventButtonJFrame.java
. This is because
the class with the main method (the one that will actually run) is the
testEventButtonJFrame

class.

// continued…

A listener with two buttons (download
here
)

If we want our
actionListener

to respond to more than 1 button,
we have to change the
actionPerformed

method so that it checks
which button

was source of the current event. We do this as follows:

Declare the two buttons as class
-
level variables; at top of the class, put:


JButton myCountButton = new JButton("count");


JButton myClearButton = new JButton("clear");


In the constructor for the class, register both buttons with the listener
(and add each button to the
JPanel

as required):

myCountButton.addActionListener(this);
myClearButton.addActionListener(this);


In the actionPerformed method, check which button was the source of
the current
ActionEvent e
, and respond accordingly:


if (e.getSource().equals(myCountButton)) {…
do whatever
}


if (e.getSource().equals(myClearButton)) {…
do whatever
}

Colors, fonts, and drawing graphics

There are lots of other things we can do with

JPanels:
change colors, set font
sizes, etc. See Liang 10.7 and 10.5, and example 10.5, for details of these. I’ll leave
them to you to read over.

We have extended
JPanel

to
MyMessageJPanel

and used
g.drawString()

to draw a string (a message) in the panel.

We can use a similar approach to draw graphics in a panel, using the predefined
graphics methods
g.drawline(), g.drawRect(), g.drawOval()

and so on. To
use these we extend
JPanel

to
JRectPanel
, for example, and in
JRectPanel

override
paintComponent()

as follows:


public void paintComponent(Graphics g){

// override
paintComponent


super.paintComponent(g);



// first do whatever
paintComponent
in
JPanel

always does


g.
drawRect
(
x,y,width,height
);


}

// draw a rectangle at x,y with the given width and height

Using the API

There are a lot of details in the

javax.swing
and

java.awt
classes I’ve
discussed here. I haven’t mentioned most of the abilities of these classes.

You should look these classes up in the API:

http://java.sun.com/j2se/

(click on ‘API specifications’ under ‘reference’, and
then pick the edition of J2SE you are using: currently probably 1.4.2).

You should look up

javax.swing

and within that look up the classes
JFrame, JPanel, JComponent,
JDialog

and see the methods that are listed. In
JComponent

you will see
subclasses such as
JTextField, JTextArea, Jbutton,
JRadioButton, JCheckBox

and so on. The API explains all of the abilites
of objects in these classes and how they are used.

Within
javax.awt

you will find the layout managers and various other useful
classes of objects.



Conclusion


GUI construction and control is not complicated, but there are loads
of details involved.


You don’t need to know all these details: my aim has been to give a
general idea of what goes on in GUI construction and in event
-
driven
programming.


If you’re interested, you can look up the various classes discussed
here in the Java API:



http://java.sun.com/j2se/

(click on ‘API specifications’ under
‘reference’, and then pick the edition of J2SE you are using:
currently probably 1.5.0 ).



There are very useful tutorials on JFrame use, event
-
driven
programming and other aspects of Java programming in the API.