CS 3230 - Lab 8

Swing Controls Lab

Today, true believers, you'll get a chance to play with some Swing GUI controls. This lab is as much about events as it is about GUI controls (the two being closely tied) so you'll get a chance to learn more about event handling. Also, it is not possible to include all the GUI controls covered in Chapter 9, so I'm just having you work with a selected few. Your application project will give you the opportunity to experiment with many more GUI controls.

Overview

Screenshot

First of all, you will be starting with the Lab8_starter.java source code as a beginning point. You will be adding features to it until it looks like this.

Here's some detail of the "Load" menu:

Note that the menu entries correspond to the buttons.

Summary of Features You Will Add

Specifications

Here's some more detail on how to add all of the above features.

Making the Hyperlinks Work

Look at the JEditorPane docs for how to do this. (Scroll down just a little bit.) You can just cut-and-paste this code into the Lab8_starter class, such that it becomes an inner class.

Don't forget to call JEditorPane.addHyperlinkListener().

Handling Back / Forward Actions

Firstly, think about the best data structure for keeping track of a list of visited URLs such that the last visited URL is the first one to be retrieved. Can you guess? You'll need to instantiate two of these: one for the "back list" (call it "backStack"), and one for the "forward list" (call it "forwardStack" or "fwdStack").

Nextly, You will need to make two more inner classes that implement the ActionListener interface, just like the LoadPage class. One of these will be called when you hit the "Back" button / menu (call it LoadPrev), the other will be called when you hit the "Forward" button / menu (call it LoadNext). Each of them will push / pop a string off of / on to the appropriate stack and call JEditorPane.setPage() to load the page. Make a new instance of each of LoadPrev and LoadNext in the same place where LoadPage is instantiated.

Making the Menus

There are three different menu classes you will deal with here: JMenuItem, JMenu, and JMenuBar.

After you instantiate each new menu item, you should add an appropriate action listener by calling addActionListener() on each one.

Making the Buttons

This is a process very similar to the menus above. Simply make three instances of JButton classes and call JButton.addActionListener() adding the appropriate ActionListener derivative to each one.

For the button images, feel free to use these:


back.gif

forward.gif

reload.gif

The best way to construct these is like so:

JButton backButton = new JButton(new ImageIcon("back.gif"));

Convenience Items

You may want to make the following small edits to improve the app:

Questions and Answers

The App seems to lock up when I load a page!

True. We are not using any extra threads in this app, so when the page loads, it ties up the single thread the app is running in. (Although I think the newer versions of the JDK (1.4.1) uses a seperate thread for the JEditorPane, so you might not experience as much of a "lockup", depending.)

What packages do I need to import?

These:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.html.*;
import java.util.Stack;

Incidentally, you can find out which packages you need to add by looking at the "Cannot resolve symbol" error messages, then looking up the class in the Java API Documentation on java.sun.com.

So, how many classes are there in this exercise?

I ended up with five:

  1. Lab8 - The frame, given to you in the starter code.
  2. LoadPage - An inner class that loads a page, also given to you in the starter code.
  3. HyperActive - A HyperLinkListerer that loads pages when you click on the links, a copy-n-paste from the docs for JEditorPane.
  4. LoadPrev - An ActionListener that responds to clicking the 'Back' button and the 'Load -> Previous' menu item. You will need to write this. Please wrap your code with a try..catch block like the one in the LoadPage class to handle the lines that print exceptions.
  5. LoadNext - An ActionListener that responds to clicking the 'Forward' button and the 'Load -> Forward' menu item. You will also need to write this; it will be very similar to the LoadPrev class.

You should make a new, named instance of both LoadPrev and LoadNext and pass these instances to the addActionListener() methods of both the buttons and the menus.

Why do I have to click the back / forward buttons twice to change the page?

Hats off to all the alert students who spotted this! The problem is caused by the way you put stuff on the forward/back stacks. The page that you are currently displaying is probably also on the top of the stack.

To cure this problem, use code like the following in your LoadPrev and LoadNext classes:

String prev;
do {
	prev = (String)backStack.pop();
} while (prev.equals(textField.getText()));
System.out.println("popped " + prev + " off the back stack");

That will make sure that you keep popping until you find the page before the one you're displaying now.

So, what do I push / pop onto / off of these stacks?

Strings. You can get the string to the current URL with HyperLinkEvent.getURL().toString(). Alternatively, if the text field is displaying the URL for the currently loaded page, you can type textField.getText()

Do you still want my name, course number and lab number at the top of the page?

Yep.

Do you really want me to name the main class "Lab8_starter"?

No. Please rename the class (and the file) to Lab8 (and Lab8.java).

The pages in this browser look kind of ugly.

So's your momma.

How can I use this stuff in my Application Project?

An excellent question. You can further develop your application project by plopping lots of GUI controls on your app, adding some Menus and maybe some Toolbars, possibly launching some Dialogs, and maybe using one of those funky Layout Managers.

Those of you that are making a web browser for your application project should find this lab useful. However, I would expect to see you add a few more features above and beyond the ones added in this lab.