Components, Panels, Applets
Panels provide the space in which you can build your Applet. You can attach any GUI Component to a Panel, including other Panels.
Specifically, the Applet class provided with Java implements a basic Panel (is a Container) that you can use directly for simple interfaces (can put other Components or Containers into it). (figure 13.2 from 21 days)
Example: (these are named badly - note these are all applets)
(figure 1)
import java.awt.*;
import java.applet.Applet;
public class myButton extends Applet { // note: this is an
// example of the use of a Button,
// Buttons are subclasses of component
Button button1;
public void init() {
button1 = new Button("Ok");
add(button1);
}
}
Notice button instantiation
Button Clearbutton;
Clearbutton = new Button("Clear");
The String you specify during the instantiation will appear on the button when it is displayed on the screen. The string will also be returned for use as identification when an event has occurred.
NOTE: There are no x, y coordinates because these are relative to the panel and platform.
Instead we will use Layout Managers. The default is the Flow Layout - fills in objects to the right until it flows to the next line (more later)
The above button doesn't help unless it does something.Recall that whenever a user clicks a button, an event happens (as with mouseDown and mouseUp events).
The button methods can be "caught" by overriding the action method of an applet. (The mouse and key events go to action methods with different signatures)
import java.awt.*;
import java.util.*;
import java.io.*;
import java.applet.Applet;
public class myButton extends Applet {
Button button1;
public void init() {
button1 = new Button("Ok");
add(button1);
}
public boolean action(Event e, Object arg) {
if (e.target instanceof Button) {
System.out.println("Button: " + arg);
}
return true;
}
public boolean mouseDown(Event e, int x, int y) {
System.out.println("Mouse works: (" + x +","+y+")");
return true; }
}
Events: these are system messages - a result of physical action by a user (usually).
One has a canvas on top of a Window. If the user clicks the mouse on the canvas, the canvas gets the event
- post the event to the object
- the object handles the event
(calls action of that object)
- if return true, says this object dealt with it also can take action and still return false so outer object does something too.
- if doesn't handle event, return false passes event to enclosing container
- if I do not hit the button, but put an else in the button action method, nothing extra happens
else {System.out.println("Non-Button event " ); }
cause I never hit the button (no object, only x,y coordinates)
- must return something at end of boolean methods
Multiple Buttons:
Distinguishing between multiple buttons can be done by using the target object passed by the Event object and comparing it to your button objects:
import java.awt.*; // includes Graphics, Event, Button, etc.
import java.applet.Applet;
/* * Simple multiple buttons test */
public class Buttons extends Applet {
Button b1, b2, b3;
public void init()
{
b1 = new Button("B1");
b2 = new Button("B2");
b3 = new Button("B3");
this.add(b1); // do we need this?
this.add(b2);
this.add(b3); }
public boolean action(Event ev, Object obj)
{
if (ev.target.equals(b1))
System.out.println ("User pressed B1 button!");
if (ev.target.equals(b2))
System.out.println ("User pressed B2 button!");
if (ev.target.equals(b3))
System.out.println ("User pressed B3 button!");
return true;
}
}
Note: here we could say ev.target == b1 since they literally are the same object. This would be faster (why?)
Other Button Types
Choice (like menus)
import java.awt.*;
import java.applet.Applet;
/* * Choice button test applet */
public class ChoiceDemo extends Applet {
public void init() {
Choice ColorChooser = new Choice();
ColorChooser.addItem("Blue");
ColorChooser.addItem("Red");
ColorChooser.addItem("Green");
add (ColorChooser); // to the applet instance of ChoiceDemo
}
public boolean action(Event ev, Object obj)
{
// Check for a label from the Choice button
if (ev.target instanceof Choice) {
String label = (String)obj;
System.out.println ("The new color is " + label); }
return true; } }
The string supplied to the addItem() method will be returned in the Object argument of a Choice event.
Checkbox Buttons are often used as state buttons. They provide toggle values on and off (T/F). The state of the button is returned as the Object argument for Checkbox events. (arg is true if checked, false otherwise) Both the name and state are returned in the Event arg. They can be retrieved using getLabel() and getState()
import java.applet.Applet;
import java.awt.*;
public class CheckBoxExample extends Applet {
Checkbox checkme;
checkme = new Checkbox("Solid");
public boolean action(Event e, Object arg) {
if (e.target instanceof Checkbox) {
System.out.println ("Checkbox: " + e.arg.toString()); }
return true; }
For the radio action (one on at a time), the Checkbox can be grouped. When one is selected, the others turn off.
import java.applet.Applet;
import java.awt.*;
public class CheckBoxExample extends Applet {
CheckboxGroup cbg;
public void init()
{ cbg = new CheckboxGroup();
add (new Checkbox("one ", cbg, true));
add (new Checkbox("two ", cbg, false));
add (new Checkbox("three", cbg, false)); } }
Another technique for Buttons: (more OO honest) Since Java is object-oriented, it gives us the capability of creating completely self-contained buttons. In these types of buttons, you build the event handling function directly into an
extended button class.
You can then add the button to your applet without worrying about any events the applet would generate.
Examples:
Suppose you actually want to make your own Button
class MyButton extends Button { // subclassing
public MyButton(String label) {
super(label);}
// Must be a constructor for this class, else
//calls constructor for super() and if you provided a string complains
public boolean action (Event e, Object arg) {
...
return true;
...}
}
Then in some class (whatever) you add the new subclass intances
class whatever {
public void init() {
add (new MyButton ("OK"); } }
Then the applet class does not deal with events from my Button, myButton does
Another example: (we have a specific kind of buton we want to subclass...we always know what that button does)
import java.awt.*;
import java.applet.Applet;
/*
* Build an OK button class that contains its own event handler.
* This means we don't have to check and see which button caused
* the event--the only events this class sees are generated by
* the button itself
*/
class okButton extends Button {
// Our constructor--we know the label for the Ok button
public okButton() {
setLabel("Ok");
}
// Our event handler--this only gets called when this Ok button
// gets pressed (so no need to do (if (e.target instanceof Button) ...)
public boolean action(Event e, Object arg) {
System.out.println("OKButton");
return true;
}
}
Test it:
public class buttonTest extends Applet {
okButton myOkButton;
public void init() {
// create a new okButton and add it to the panel
myOkButton = new okButton();
add(myOkButton);
}
}
Notice there is no action() method in the buttonTest applet class. The OkButton class will handle the button events.
If we had placed other objects in the applet, we could still include an action() method to handle their events.
Context:
So far we have been within an Applet. Consider applet
init()
make an instance
of button
...
\ reference to
MyButton
action
...
another applet
adds button
Suppose you have a button (or text area, etc) in a different applet (or different component is a better way to say this). We want a buttons actions to affect things in various applets. Then MyButton needs a reference to the applet object. So, one part is to send reference to self so it knows where it is.
add (new MyButton (this, "OK");
// this is the container where new is called
in method: public MyButton (Object this, String label)
OR, the add could be in some other applet.
In the interface, the button observer can pass the generic applet
TextFields
For direct user input of information via the keyboard.
You can choose one of four options:
- blank
- blank with specified length
- predefined text
- predefined text with a specified length
import java.awt.*;
import java.applet.Applet;
public class tf extends Applet {
TextField tf1, tf2, tf3, tf4;
public void init() {
tf1 = new TextField();
tf2 = new TextField(20);
tf3 = new TextField("Hello");
tf4 = new TextField("Hello", 30);
add(tf1);
add(tf2);
add(tf3);
add(tf4);
}
public boolean action(Event e, Object arg) {
if (e.target instanceof TextField) {
System.out.println("TextField: " + arg); } }
}
When the user hits return in a text field, the action generates a text field event. You catch this event in the action method.
Text Areas: Java also allows programmers to use multi-lined text as a field (text area). For text areas you must also specify the number of rows:
import java.awt.*;
import java.applet.Applet;
public class ta extends Applet {
TextArea ta2;
public void init() {
ta2 = new TextArea("Hello!", 5, 40); // a 5 x 40 text area
ta2.setEditable(false); // would then be read-only
add(ta2); } }
To access the text currently in a TextArea you can use getText()
System.out.println (ta2.getText());
TextAreas do not generate any unusual events, but you can use other events to drive access to the text in the event handler:
public boolean action(Event e, Object arg) {
if (e.target instanceof Button) {
if ("Send".equals (arg)) {
//User pressed the Send button so grab the text
String textToSend = ta1.getText();
System.out.println("Sending: " + texttoSend);
mySendFunction(textToSend); }
}
else { ...}
}
The above is a good example of how you might have components in different components (make sense) and you want to have a handle on them (use of self as parameter) OR how subclassing buttons can direct actions (when the send button was made, it could have made an IV to ta1)
Lists:
List l = new List (5, false);
Displays 5 lines of the list at a time; true allows multiple selection, false allows only one.
Applet provides a scrollbar for list items that exceed the viewing area
import java.awt.*;
import java.applet.Applet;
public class list extends Applet {
public void init() {
List l = new List(6, true);
l.addItem("Mercury");
l.addItem("Venus");
l.addItem("Earth");
l.addItem("Mars");
l.addItem("Jupiter");
l.addItem("Saturn");
l.addItem("Neptune");
l.addItem("Uranus");
l.addItem("Pluto");
add(l);
}
public boolean action(Event e, Object arg) {
System.out.println("Event: " + arg);
return true;
}
}
To access the selected items from a list, use the getSelectedItem() or getSelectedItems() methods.
For single selected lists, any double-click selection in a list will trigger an event that you catch in the action() method (first click chooses, second click triggers event) (this is questionable given latest communications on clicking)
For multiple-select lists you need an external event to trigger your actions. For example:
public boolean action(Event e, Object arg) {
...
if (e.target instanceof Button) {
...
if ("Ok".equals(arg)) {
string[] selected;
selected = l.getSelectedItems();
for (int i = 0; i < selected.length; i++) {
System.out.println(selected[i]); }
}
}
}
Scrollbar example - test it and see how it works
import java.awt.*;
import java.util.*;
import java.io.*;
import java.applet.Applet;
public class slider extends Applet {
Scrollbar redSlider, greenSlider, blueSlider;
Scrollbar ranger;
Panel p1, p2;
Button b1;
public void init() {
setLayout(new BorderLayout(15,15));
p1 = new Panel();
b1 = new Button("Test");
redSlider = new Scrollbar(Scrollbar.VERTICAL, 0, 1, 0, 256);
greenSlider = new Scrollbar(Scrollbar.VERTICAL, 0, 1, 0, 256);
blueSlider = new Scrollbar(Scrollbar.VERTICAL, 0, 1, 0, 256);
ranger = new Scrollbar(Scrollbar.HORIZONTAL, 1, 64, 1, 256);
p1.add(redSlider);
p1.add(greenSlider);
p1.add(blueSlider);
add("Center",ranger);
add("North", p1);
add("South", b1);
}
public boolean handleEvent(Event e) {
if (e.target instanceof Scrollbar) {
System.out.println("Scrollbar: " + ((Scrollbar)e.target).getValue());
return true;
}
return super.handleEvent(e);
}
public boolean action(Event e, Object arg) {
System.out.println("Event" + arg);
return true;
}
public boolean mouseDown(Event e, int x, int y) {
System.out.println("Mouse works: (" + x +","+y+")");
return true;
}
}
LayoutManager
- FlowLayout
- BorderLayout
- GridLayout
FlowLayout
Basic - default for every panel, default placement is center
Components added to a panel follow each other in a list fashion. You position
horizontally, you can specify the spaces between each component.
setLayout(new FlowLayout(FlowLayout.LEFT,20,5)); // RIGHT
import java.awt.*;
import java.util.*;
import java.io.*;
import java.applet.Applet;
public class layoutTest extends Applet {
Button testButton,test2;
String myDisplay="Starting out...";
TextArea type;
List l;
FileInputStream fis;
public void init() {
setLayout(new FlowLayout(FlowLayout.LEFT,20,5));
testButton=new Button("Left");
test2=new Button("Right");
try {
fis=new FileInputStream("/etc/motd");
} catch (FileNotFoundException e) { }
String fileText;
byte b[] = new byte[1024];
try {
fis.read(b);
} catch (IOException e) { }
fileText = new String(b,0);
type=new TextArea(fileText,3,20);
l = new List(2,true);
add(testButton);
add(test2);
add(type);
l.addItem("List 1");
l.addItem("List 2");
//add(l);
}
public boolean action(Event e, Object arg) {
if (e.target instanceof Button) {
if("Left".equals(arg)) {
myDisplay="Test Button 1" + type.getText();
}
else if ("Right".equals(arg)) {
myDisplay="Test Button 2";
String[] sel;
sel = l.getSelectedItems();
for (int i = 0; i < sel.length; i++) {
System.out.println(sel[i]);
}
}
else {
myDisplay="Button: " + arg;
}
}
else if (e.target instanceof List) {
myDisplay="List: " + arg;
}
else if (e.target instanceof TextField) {
myDisplay="Text: " + arg;
}
else if (e.target instanceof TextArea) {
myDisplay="Text: " + arg;
}
else {
myDisplay="Not a button event.";
}
repaint();
return true;
}
public boolean mouseDown(Event e, int x, int y) {
myDisplay="Mouse works: (" + x +","+y+")";
repaint();
return true;
}
public void paint(Graphics g) {
g.drawString(myDisplay, 40,375);
}
}
BorderLayout
Border provides 5 areas: North, South, East, West, Center
The center represents everything once the directions are filled
import java.awt.*;
import java.applet.Applet;
public class buttonDir extends Applet {
Button buttonN, buttonS, buttonW, buttonE, buttonC;
public viod init() {
setLayout (new Borderlayout());
buttonN = new Button ("North"); // instantiates buttons
buttonS = new Button ("South");
buttonE = new Button ("East");
buttonW = new Button ("West");
buttonC = new Button ("Center");
add ("North", buttonN); // places in regions
add ("South", buttonS);
add ("East", buttonE);
add ("West", buttonW);
add ("Center", buttonC); }
}
GridLayout
Rows and Columns (fills across row (i.e. columns) first)
column major?
1 2
3 4
5 6
import java.awt.*;
import java.applet.Applet;
public class buttonGrid extends Applet {
Button button1, button2, button3, button4, button5, button6;
public viod init() {
setLayout (new Gridlayout(3,2)); // 3 rows , 2 columns
button1 = new Button ("1"); // instantiates buttons
button2 = new Button ("2");
button3 = new Button ("3");
button4 = new Button ("4");
button5 = new Button ("5");
button6 = new Button ("6");
add (button1); // fill across row first
add (button2);
add (button3); // next row
add (button4);
add (button5);
add (button6); }
}
See GridBagLayout in "Java in a Nutshell" (page 108-114, and 256-257) (most powerful)
Canvases
If your applet will deal with graphics directly, canvases are a good idea. Once you start filling up a window with lots of interface elements and multiple panels, it is best not to draw directly onto the window surface any more. This is because your drawing will interfere with the buttons. Instead you add a canvas to the window.
A canvas is simply a rectangular area in which you can draw. (In contrast, a panel is a rectangular area into which you can place user interface components.) Making a canvas is a bit more complex than using a panel because you need to specify how to draw on the canvas. This means you must derive a new class from Canvas and then override the paint method in your extended class.
Canvases provide a basic component that catches expose events, mouse events, and other events. While the basic canvas does nothing with these events, you can extend canvas to create your own functioning canvases.
import java.awt.*;
import java.applet.Applet;
import myCanvas;
public class canvas extends Applet {
Panel p1;
Button b1;
public void init() {
setLayout(new BorderLayout(15,15));
b1 = new Button("Test");
myCanvas c1 = new myCanvas(100,100);
add("Center", c1);
add("South", b1); }
public boolean handleEvent(Event e) {
if (e.target instanceof Scrollbar) {
System.out.println("Scrollbar: " + ((Scrollbar)e.target).getValue());
return true; }
return super.handleEvent(e); }
public boolean action(Event e, Object arg) {
System.out.println("Event: " + arg);
return true; }
public boolean mouseDown(Event e, int x, int y) {
System.out.println("Mouse works: (" + x +","+y+")");
return true;
}
}
By creating a subclass of canvas, we can override the usual event handling methods in addition to the paint methods.
Canvases simplify the production of applets requiring unique functionality for several distinct areas.
Below we override the mouseDown() and paint() methods
public class myCanvas extends Canvas {
private int width;
private int height;
public myCanvas(int w, int h) {
width = w;
height = h;
reshape(0,0,w,h);
}
public void paint(Graphics g) {
g.setColor(Color.blue);
g.fillRect(0,0,width,height);
}
public boolean mouseDown(Event e, int x, int y) {
if (( x < width) && (y < height)) {
System.out.println("Canvas mouse works: (" + x + "," + y + ")");
return true;
}
//return super.mouseDown(e, x, y);
return false;
}
}