Tuesday 6 March 2012

Windows, Networking, and Other Tidbits

  • Windows, Networking, and Other Tidbits
    • Windows, Menus, and Dialog Boxes
      • Frames
      • Menus
        • Menus and Menubars
        • Menu Items
        • Menu Actions
        • An Example
      • Dialog Boxes
      • File Dialogs
      • Window Events
      • Using AWT Windows in Stand-Alone Applications
    • Networking in Java
      • Creating Links Inside Applets
      • Opening Web Connections
      • openStream()
      • The URLconnection Class
      • Sockets
    • Other Applet Hints
      • The showStatus Method
      • Applet Information
      • Communicating Between Applets
    • Summary
    • Q&A


Windows, Networking, and Other Tidbits

Here you are on the last day of the second week, and you're just about finished with applets and the AWT. With the information you'll learn today, you can create a wide variety of applets and applications using Java. Next week's lessons provide more of the advanced stuff that you'll need if you start doing really serious work in Java.
Today, to finish up this week, there are three very different topics:
  • Windows, menus, and dialog boxes—the last of the AWT classes that enable you to pop up real windows from applets, and to create stand-alone Java applications that have their own windows
  • Networking—how to load new HTML files from an Java-enabled browser, how to retrieve files from Web sites, and some basics on how to work with generic sockets in Java
  • Extra tidbits—the smaller stuff that didn't fit in anywhere else, but that might be useful to you as you write your Java applets and applications

Windows, Menus, and Dialog Boxes

Today, you'll finish up the last bits of the AWT that didn't fit into yesterday's lesson. In addition to all the graphics, events, UI, and layout mechanisms that the AWT provides, it also provides windows, menus, and dialog boxes, enabling to you create fully featured applications either as part of your applet or independently for stand-alone Java applications.

Frames

The AWT Window class enables you to create windows that are independent of the browser window containing the applet—that is, separate popup windows with their own titles, resize handles, and menubars.
The Window class provides basic behavior for windows. Most commonly, instead of using the Window class, you'll use Window's subclasses, Frame and Dialog. The Frame class enables you to create a fully functioning window with a menubar. Dialog is a more limited window for dialog boxes. You'll learn more about dialog boxes later on in this section.
To create a frame, use one of the following constructors:
  • new Frame() creates a basic frame without a title.
  • new Frame(String) creates a basic frame with the given title.

Frames are containers, just like panels are, so you can add other components to them just as you would regular panels, using the add() method. The default layout for windows is BorderLayout:
win = new Frame("My Cool Window");

win.setLayout(new BorderLayout(10, 20));

win.add("North", new Button("Start"));

win.add("Center", new Button("Move"));
To set a size for the new window, use the resize() method. To set a location for where the window appears, use the move() method. Note that the location() method can tell you where the applet window is on the screen so that you can pop up the extra window in a relative position to that window (all these methods are defined for all containers, so you can use them for applets, windows, and the components inside them, subject to the current layout):
win.resize(100, 200);

Dimension d = location();

win.move(d.width + 50, d.height + 50);
When you initially create a window, it's invisible. You need to use the show() method to make the window appear on the screen (you can use hide() to hide it again):
win.show();
Listing 14.1 shows an example of a simple applet with a popup window (both the applet and the window are shown in Figure 14.1). The applet has two buttons: one to show the window, and one to hide the window. The window itself, created from a subclass called MyFrame contains a single label: "This is a Window." You'll use this basic window and applet all through this section, so the more you understand what's going on here the easier it will be later.

Figure 14.1. Windows.
    Listing 14.1. A popup window.
1: public class GUI extends java.applet.Applet {

 2:     Frame window;

 3:

 4:     public void init() {

 5:         add(new Button("Open Window"));

 6:         add(new Button("Close Window"));

 7:

 8:         window = new MyFrame("A Popup Window");

 9:         window.resize(150, 150);

10:         window.show();

11:     }

12:

13:     public boolean action(Event evt, Object arg) {

14:         if (evt.target instanceof Button) {

15:             String label = (String)arg;

16:             if (label.equals("Open Window")) {

17:                 if (!window.isShowing())

18:                 window.show();

19:             }

20:             else if (label == "Close Window") {

21:                 if (window.isShowing())

22:                     window.hide();

23:             }

24:             return true;

25:         }

26:         else return false;

27:     }

28: }

29: 

30: class MyFrame extends Frame {

31:     Label l;

32:     MyFrame(String title) {

33:     super(title);

34:     setLayout(new GridLayout(1, 1));

35:     l = new Label("This is a Window", Label.CENTER);

36:     add(l);

37: }

Menus

Each new window you create can have its own menubar along the top of the screen. Each menubar can have a number of menus, and each menu, in turn, can have menu items. The AWT provides classes for all these things called, respectively, MenuBar, Menu, and MenuItem.
Menus and Menubars
To create a menubar for a given window, create a new instance of the class MenuBar:
MenuBar mb = new MenuBar();
To set this menubar as the default menu for the window, use the setMenuBar() method on the window:
window.setMenuBar(mb);
Add individual menus (File, Edit, and so on) to the menubar by creating them and then adding them to the menubar:
Menu m = new Menu("File");

mb.add(m);
Some systems enable you to indicate a special help menu, which may be drawn on the right side of the menubar. You can indicate that a specific menu is the help menu by using the setHelpMenu() method. The given menu should already be added to the menu itself:
Menu hm = new Menu("Help");

mb.add(hm);

mb.setHelpMenu(hm);
If, for any reason, you want to prevent a user from selecting a menu, you can use the disable() command on that menu (and the enable() command to make it available again):
m.disable();
Menu Items
There are four kinds of items you can add to individual menus:
  • Instances of the class MenuItem, for regular menu items
  • Instances of the class CheckBoxMenuItem, for toggled menu items
  • Other menus, with their own menu items
  • Separators, for lines that separate groups of items on menus

Regular menu items are added by using the MenuItem class. Add them to a menu using the add() method:
Menu m = new Menu("Tools");

m.add(new MenuItem("Info"));

m.add(new MenuItem("Colors"));
Submenus can be added simply by creating a new instance of Menu and adding it to the first menu. You can then add items to that menu:
Menu sb = new Menu("Sizes");

m.add(sb);

sb.add(new MenuItem("Small"));

sb.add(new MenuItem("Medium"));

sb.add(new MenuItem("Large"));
The CheckBoxMenuItem class creates a menu item with a checkbox on it, enabling the menu state to be toggled on and off (selecting it once makes the checkbox appear selected; selecting it again unselects the checkbox). Create and add a checkbox menu item the same way you create and add regular menu items:
CheckboxMenuItem coords =

    new CheckboxMenuItem("Show Coordinates");

m.add(coords);
Finally, to add a separator to a menu (a line used to separate groups of items in a menu), create and add a menu item with a single dash (-) as the label.
MenuItem msep = new MenuItem("-");

m.add(msep);
Any menu item can be disabled by using the disable() method and enabled again using enable(). Disabled menu items cannot be selected:
MenuItem mi = new MenuItem("Fill");

m.addItem(mi);

mi.disable();
Menu Actions
The act of selecting a menu item causes an action event to be generated. You can handle that action the same way you handle other action methods—by overriding action(). Both regular menu items and checkbox menu items have actions that generate an extra argument representing the label for that menu. You can use that label to determine which action to take. Note, also, that because CheckBoxMenuItem is a subclass of MenuItem, you don't have to treat that menu item as a special case:
public boolean action(Event evt, Object arg) {

    if (evt.target instanceof MenuItem) {

        String label = (String)arg;

        if (label.equals("Show Coordinates")) toggleCoords();

        else if (label.equals("Fill")) fillcurrentArea();

        return true;

    }

    else return false;

}
An Example
Let's add a menu to the window you created in the previous section. Add it to the constructor method in the MyFrame class (Figure 14.2 shows the resulting menu):

Figure 14.2. A menu.
MyFrame(String title) {

    super(title);

    MenuBar mb = new MenuBar();

    Menu m = new Menu("Colors");

    m.add(new MenuItem("Red"));

    m.add(new MenuItem("Blue"));

    m.add(new MenuItem("Green"));

    m.add(new MenuItem("-"));

    m.add(new CheckboxMenuItem("Reverse Text"));

    mb.add(m);

    mb.setHelpMenu(m);

    setMenuBar(mb);

    ...

}
This menu has four items: one each for the colors red, blue, and green (which, when selected, change the background of the window), and one checkbox menu item for reversing the color of the text (to white). To handle these menu items, you need an action() method:
public boolean action(Event evt, Object arg) {

    String label = (String)arg;

    if (evt.target instanceof MenuItem) {

      if (label.equals ("Red")) setBackground(Color.red);

      else of (label.equals("Blue")) setBackground(Color.blue);

      else if (label.equals("Green")) setBackground(Color.green);

      return true;

    }

    if (evt.target instanceof CheckboxMenuItem) {

      if (getForeground() == Color.black)

        setForeground(Color.white);

      else setForeground(Color.black);

      return true;

    }

    return false;

}

Dialog Boxes

Dialog boxes are functionally similar to frames in that they pop up new windows on the screen. However, dialog boxes are intended to be used for transient windows—for example, windows that let you know about warnings, windows that ask you for specific information, and so on. Dialogs don't usually have titlebars or many of the more general features that windows have (although you can create one with a titlebar), and they can be made nonresizable or modal.
A modal dialog prevents input to any of the other windows on the screen until that dialog is dismissed.
The AWT provides two kinds of dialog boxes: the Dialog class, which provides a generic dialog, and FileDialog, which produces a platform-specific dialog to choose files to save or open.
To create a generic dialog, use one of these constructors:
  • Dialog(Frame, boolean) creates an initially invisible dialog, attached to the current frame, which is either modal (true) or not (false).
  • Dialog(Frame, String, boolean) is the same as the previous constructor, with the addition of a titlebar and a title indicated by the string argument.

Note that because you have to give a dialog a Frame argument, you can attach dialogs only to windows that already exist independently of the applet itself.
The dialog window, like the frame window, is a panel on which you can lay out and draw UI components and perform graphics operations, just as you would any other panel. Like other windows, the dialog is initially invisible, but you can show it with show() and hide it with hide().
Let's add a dialog to that same example with the popup window. You'll add a menu item for changing the text of the window, which brings up the Enter Text dialog box (see Figure 14.3).

Figure 14.3. The Enter Text dialog.
To add this dialog, first add a menu item to that window (the constructor method for the MyFrame class) to change the text the popup window displays:
m.add(new MenuItem("Set Text..."));
In that same method, you can create the dialog and lay out the parts of it (it's invisible by default, so you can do whatever you want to it and it won't appear on screen until you show it):
dl = new Dialog(this, "Enter Text", true);

dl.setLayout(new GridLayout(2, 1, 30, 30));

tf = new TextField(l.getText(), 20);

dl.add(tf);

dl.add(new Button("OK"));

dl.resize(150, 75);
The action of choosing the menu item you just added brings up the dialog; choosing the OK button dismisses it. So you need to add behavior to this class's action method so that the dialog works right. To the menu item tests, add a line for the new menu item:
if (evt.target instanceof MenuItem) {

    if (label.equals("Red")) setBackground(Color.red);

    if (label.equals("Blue")) setBackground(Color.blue);

    if (label.equals("Green")) setBackground(Color.green);

    if (label.equals("Set Text...")) dl.show();

}
Then, because OK is a button, you have to add a special case for that button separate from the menu items. In this special case, set the text of the window to the text that was typed into the text field, and then hide the dialog again:
if (evt.target instanceof Button) {

    if (label.equals("OK")) {

        l.setText(tf.getText());

        dl.hide();

    }

}

File Dialogs

FileDialog provides a basic file open/save dialog box that enables you to access the file system. The FileDialog class is system-independent, but depending on the platform, the standard Open File dialog is brought up.

Note: For applets, you can bring up the file dialog, but due to security restrictions you can't do anything with it (or, if you can, access to any files on the local system is severely restricted). FileDialog is much more useful in stand-alone applications.

To create a file dialog, use the following constructors:
  • FileDialog(Frame, String) creates an Open File dialog, attached to the given frame, with the given title. This form creates a dialog to load a file.
  • FileDialog(Frame, String, int) also creates a file dialog, but that integer argument is used to determine whether the dialog is for loading a file or saving a file (the only difference is the labels on the buttons; the file dialog does not actually open or save anything). The possible options for the mode argument are FileDialog.LOAD and FileDialog.SAVE.

After you create a FileDialog instance, use show() to display it:
FileDialog fd = new FileDialog(this, "FileDialog");

fd.show();
When the reader chooses a file in the file dialog and dismisses it, you can then access the filename they chose by using the getDirectory() and getFile() methods; both return strings indicating the values the reader chose. You can then open that file by using the stream and file handling methods (which you'll learn about next week) and then read from or write to that file.

Window Events

Yesterday, you learned about writing your own event handler methods, and you noted that the Event class defines many standard events for which you can test. Window events are part of that list, so if you use windows, these events may be of interest to you. Table 14.1 shows those events.
    Table 14.1. Window Events from the Event Class.
WINDOW_DESTROY
Generated when a window is destroyed (for example, when the browser or applet viewer has quit)
WINDOW_EXPOSE
Generated when the window is brought forward from behind other windows
WINDOW_ICONIFY
Generated when the window is iconified
WINDOW_DEICONIFY
Generated when the window is restored from an icon
WINDOW_MOVED
Generated when the window is moved

Using AWT Windows in Stand-Alone Applications

Because frames are general-purpose mechanisms for creating AWT windows with panels, you can use them in your stand-alone Java applications and easily take advantage of all the applet capabilities you learned about this week. To do this, write your application as if it were an applet (inheriting from the Applet class and using threads, graphics, and UI components as necessary), and then add a main() method. Here's one for a class called MyAWTClass:
public static void main(String args[]) {

    Frame f = new Frame("My Window");

    MyAWTClass mac = new MyAWTClass();

    mac.init();

    mac.start();

    f.add("Center", mac);

    f.resize(300, 300);

    f.show();

}
This main() method does five things:
  • It creates a new frame to hold the applet.
  • It creates an instance of the class that defines that method.
  • It duplicates the applet environment calls to init() and start().
  • It adds the applet to the frame and resizes the frame to be 300 pixels square.
  • It shows the frame on the screen.

By using this mechanism, you can create a Java program that can function equally well as an applet or an application—just include init() for applets and main() for applications.
If you do create an application that uses this mechanism, be careful of your init() methods that get parameters from an HTML file. When you run an applet as an application, you don't have the HTML parameters passed into the init() method. Pass them in as command-line arguments, instead, and handle them in your main() method. Then set a flag so that the init() method doesn't try to read parameters that don't exist.

Networking in Java

Networking is the capability of making connections from your applet or application to a system over the network. Networking in Java involves classes in the java.net package, which provide cross-platform abstractions for simple networking operations, including connecting and retrieving files by using common Web protocols and creating basic Unix-like sockets. Used in conjunction with input and output streams (which you'll learn much more about next week), reading and writing files over the network becomes as easy as reading or writing to files on the local disk.
There are restrictions, of course. Java applets cannot read or write from the disk on the machine that's running them without your express permission, and, depending on the browser, not at all. Depending on the browser, Java applets may not be able to connect to systems other than the one upon which they were originally stored. Even given these restrictions, you can still accomplish a great deal and take advantage of the Web to read and process information over the Net.
This section describes three ways you can communicate with systems on the Net:
  • showDocument(), which enables an applet to tell the browser to load and link to another page on the Web
  • openStream(), a method that opens a connection to a URL and enables you to extract data from that connection
  • The socket classes, Socket and ServerSocket, which enable you to open standard socket connections to hosts and read to and write from those connections

Creating Links Inside Applets

Probably the easiest way to use networking inside an applet is to tell the browser running that applet to load a new page. You can use this, for example, to create animated image maps that, when clicked, load a new page.
To link to a new page, you create a new instance of the class URL. You saw some of this when you worked with images, but let's go over it a little more thoroughly here.
The URL class represents a uniform resource locator. To create a new URL, you can use one of four different forms:
  • URL(String, String, int, String) creates a new URL object, given a protocol (http, ftp, gopher, file), a host name (www.lne.com, ftp.netcom.com), a port number (80 for http), and a filename or pathname.
  • URL(String, String, String) does the same thing as the previous form, minus the port number.
  • URL(URL, String) creates a URL, given a base path and a relative path. For the base, you can use getDocumentBase() for the URL of the current HTML file, or getCodeBase() for the URL of the Java applet class file. The relative path will be tacked onto the last directory in those base URLs (just like with images and sounds).
  • URL(String) creates a URL object from a URL string (which should include the protocol, hostname, optional port name, and filename).

For that last one (creating a URL from a string), you have to catch a malformed URL exception, so surround the URL constructor with a try...catch:
String url = "http://www.yahoo.com/";

try { theURL = new URL(url); }

catch ( MalformedURLException e) {

    System.out.println("Bad URL: " + theURL);

}
Getting a URL object is the hard part. Once you have one, all you have to do is pass it to the browser. Do this by using this single line of code, where theURL is the URL object to link to:
getAppletContext().showDocument(theURL);
The browser that contains your URL will then load and display the document at that URL.
Listing 14.2 shows a simple applet that displays three buttons that represent important Web locations (the buttons are shown in Figure 14.4). Clicking on the buttons causes the document to be loaded from the locations to which those buttons refer.

Figure 14.4. Bookmark buttons.
    Listing 14.2. Bookmark buttons.
1: import java.awt.*;

 2: import java.net.URL;

 3: import java.net.MalformedURLException;

 4:

 5: public class ButtonLink extends java.applet.Applet {

 6:

 7:    Bookmark bmlist[] = new Bookmark[3];

 8:

 9:    public void init() {

10:        bmlist[0] = new Bookmark("Laura's Home Page",

11:             "http://www.lne.com/lemay/");

12:         bmlist[1] = new Bookmark("Yahoo",

13:             "http://www.yahoo.com");

14:         bmlist[2]= new Bookmark("Java Home Page",

15:             "http://java.sun.com");

16:

17:         setLayout(new GridLayout(bmlist.length,1, 10, 10));

18:         for (int i = 0; i < bmlist.length; i++) {

19:             add(new Button(bmlist[i].name));

20:         }

21:     }

22:

23:     public boolean action(Event evt, Object arg) {

24:         if (evt.target instanceof Button) {

25:             LinkTo((String)arg);

26:             return true;

27:         }

28:         else return false;

29:     }

30: 

31:     void LinkTo(String name) {

32:         URL theURL = null;

33:         for (int i = 0; i < bmlist.length; i++) {

34:             if (name.equals(bmlist[i].name))

35:                 theURL = bmlist[i].url;

36:         }

37:         if (theURL != null)

38:             getAppletContext().showDocument(theURL);

39:     }

40: }

41:

42: class Bookmark {

43:     String name;

44:     URL url;

45:

46:     Bookmark(String name, String theURL) {

47:         this.name = name;

48:         try { this.url = new URL(theURL); }

49:         catch ( MalformedURLException e) {

50:             System.out.println("Bad URL: " + theURL);

51:         }

52:     }

53: }
Two classes make up this applet: the first implements the actual applet itself, the second is a class representing a bookmark. Bookmarks have two parts: a name and a URL.
This particular applet creates three bookmark instances and stores them in an array of bookmarks (this applet could be easily modified to accept bookmarks as parameters from an HTML file). For each bookmark, a button is created whose label is the value of the bookmark's name.
When the buttons are pressed, the linkTo() method is called, which tells the browser to load the URL referenced by that bookmark.

Opening Web Connections

Rather than asking the browser to just load the contents of a file, sometimes you might want to get hold of that file's contents so that your applet can use them. If the file you want to grab is stored on the Web, and can be accessed using the more common URL forms (http, ftp, and so on), your applet can use the URL class to get it.
Note that for security reasons, applets can by default connect back only to the same host from which they originally loaded. This means that if you have your applets stored on a system called www.myhost.com, the only machine your applet can open a connection to will be that same host (and that same host name, so be careful with host aliases). If the file the applet wants to retrieve is on that same system, using URL connections is the easiest way to get it.

openStream()

URL defines a method called openStream(), which opens a network connection using the given URL and returns an instance of the class InputStream (part of the java.io package). If you convert that stream to a DataInputStream (with a BufferedInputStream in the middle for better performance), you can then read characters and lines from that stream (you'll learn all about streams on Day 19). For example, these lines open a connection to the URL stored in the variable theURL, and then read and echo each line of the file to the standard output:
try {

    InputStream in = theURL.openStream();

    DataInputStream data = new DataInputStream(new BufferedInputStream(in);

    String line;

    while ((line = data.readLine()) != null) {

        System.out.println(line);

    }

}

catch (IOException e) {

    System.out.println("IO Error: " + e.getMessage());

}

Note: You need to wrap all those lines in a try...catch statement to catch IOExceptions generated.

Here's an example of an applet that uses the openStream() method to open a connection to a Web site, reads a file from that connection (Edgar Allen Poe's poem "The Raven"), and displays the result in a text area. Listing 14.3 shows the code; Figure 14.5 shows the result after the file has been read.

Figure 14.5. The GetRaven class.
    Listing 14.3. The GetRaven class.
1: import java.awt.*;

 2: import java.io.DataInputStream;

 3: import java.io.BufferedInputStream;

 4: import java.io.IOException;

 5: import java.net.URL;

 6: import java.net.URLConnection;

 7: import java.net.MalformedURLException;

 8:

 9: public class GetRaven extends java.applet.Applet

10:     implements Runnable {

11:

12:     URL theURL;

13:     Thread runner;

14:     TextArea ta = new TextArea("Getting text...", 30, 70);

15:

16:     public void init() {

17:         String url = "http://www.lne.com/Web/Java/raven.txt";

18:         try { this.theURL = new URL(url); }

19:         catch ( MalformedURLException e) {

20:             System.out.println("Bad URL: " + theURL);

21:         }

22:         add(ta);

23:     }

24:

25:     public Insets insets() {

26:         return new Insets(10,10,10,10);

27:     }

28:

29:     public void start() {

30:         if (runner == null) {

31:             runner = new Thread(this);

32:             runner.start();

33:         }

34:     }

35:

36:     public void stop() {

37:         if (runner != null) {

38:             runner.stop();

39:             runner = null;

40:         }

41:     }

42:

43:     public void run() {

44:         InputStream conn;

45:         DataInputStream data;

46:         String line;

47:         StringBuffer buf = new StringBuffer();

48:

49:         try {

50:             conn = theURL.openStream();

51:             data = new DataInputStream(new BufferedInputStream(

52:                 conn));

53:

54:             while ((line = data.readLine()) != null) {

55:                 buf.append(line + "\n");

56:             }

57:

58:             ta.setText(buf.toString());

59:         }

60:         catch (IOException e) {

61:             System.out.println("IO Error:" + e.getMessage());

62:         }

63:     }

64: }
The init() method (lines 16 to 23) sets up the URL and the text area in which that file will be displayed. The URL could be easily passed into the applet via an HTML parameter; here, it's just hard-coded for simplicity.
Because it might take some time to load the file over the network, you put that routine into its own thread and use the familiar start(), stop(), and run() methods to control that thread.
Inside run() (lines 43 to 63), the work takes place. Here, you initialize a bunch of variables and then open the connection to the URL (using the openStream() method in line 50). Once the connection is open, you set up an input stream in lines 51 to 55 and read from it, line by line, putting the result into an instance of StringBuffer (a string buffer is a modifiable string).
Once all the data has been read, line 58 converts the StringBuffer object into a real string and then puts that result in the text area.
One other thing to note about this example is that the part of the code that opened a network connection, read from the file, and created a string is surrounded by a try and catch statement. If any errors occur while you're trying to read or process the file, these statements enable you to recover from them without the entire program crashing (in this case, the program exits with an error, because there's little else to be done if the applet can't read the file). try and catch give you the capability of handling and recovering from errors. You'll learn more about exceptions on Day 17.

The URLconnection Class

URL's openStream() method is actually a simplified use of the URLconnection class. URLconnection provides a way to retrieve files by using URLs—on Web or FTP sites, for example. URLconnection also enables you to create output streams if the protocol allows it.
To use a URL connection, you first create a new instance of the class URLconnection, set its parameters (whether it enables writing, for example), and then use the connect() method to open the connection. Keep in mind that, with a URL connection, the class handles the protocol for you based on the first part of the URL, so you don't have to make specific requests to retrieve a file; all you have to do is read it.

Sockets

For networking applications beyond what the URL and URLconnection classes offer (for example, for other protocols or for more general networking applications), Java provides the Socket and ServerSocket classes as an abstraction of standard socket programming techniques.

Note: I don't have the space to give you a full explanation of how socket programming works. If you haven't worked with sockets before, see whether openStream() will meet your needs. If you really need to do more, any book that discusses socket programming will give you the background you need to work with Java's sockets.

The Socket class provides a client-side socket interface similar to standard Unix sockets. To open a connection, create a new instance of Socket (where hostname is the host to connect to, and portnum is the port number):
Socket connection = new Socket(hostname, portnum);

Note: If you use sockets in an applet, you are still subject to the security restrictions about where you can connect.

Once the socket is open, you can use input and output streams to read and write from that socket (you'll learn all about input and output streams on Day 19):
DataInputStream in = new DataInputStream(

    new BufferedInputStream(connection.getInputStream()));

DataOutputStream out= new DataOutputStream(

    new BufferedOutputStream(connection.getOutputStream()));
Once you're done with the socket, don't forget to close it (this also closes all the input and ouput streams you may have set up for that socket):
connection.close();
Server-side sockets work similarly, with the exception of the accept() method. A server socket listens on a TCP port for a connection from a client; when a client connects to that port, the accept() method accepts a connection from that client. By using both client and server sockets, you can create applications that communicate with each other over the network.
To create a server socket and bind it to a port, create a new instance of ServerSocket with the port number:
ServerSocket sconnection = new ServerSocket(8888);
To listen on that port (and to accept a connection from any clients if one is made), use the accept() method:
sconnection.accept();
Once the socket connection is made, you can use input and output streams to read from and write to the client.
See the java.net package for more information about Java sockets.

Other Applet Hints

On this, the last section of the last day of the second week, let's finish up with some small hints that didn't fit in anywhere else: using showStatus() to print messages in the browser' status window, providing applet information, and communicating between multiple applets on the same page.

The showStatus Method

The showStatus() method, available in the applet class, enables you to display a string in the status bar of the browser, which contains the applet. You can use this for printing error, link, help, or other status messages:
getAppletContext().showStatus("Change the color");
The getAppletContext() method enables your applet to access features of the browser that contains it. You already saw a use of this with links, wherein you could use the showDocument() method to tell the browser to load a page. showStatus() uses that same mechanism to print status messages.

Note: showStatus() may not be supported in all browsers, so do not depend on it for your applet's functionality or interface. It is a useful way of communicating optional information to your user—if you need a more reliable method of communication, set up a label in your applet and update it to reflect changes in its message.

Applet Information

The AWT gives you a mechanism for associating information with your applet. Usually, there is a mechanism in the browser viewing the applet to view display information. You can use this mechanism to sign your name or your organization to your applet, or to provide contact information so that users can get hold of you if they want.
To provide information about your applet, override the getAppletInfo() method:
public String getAppletInfo() {

    return "GetRaven copyright 1995 Laura Lemay";

}

Communicating Between Applets

Sometimes you want to have an HTML page that has several different applets on it. To do this, all you have to do is include several different iterations of the applet tag—the browser will create different instances of your applet for each one that appears on the HTML page.
What if you want to communicate between those applets? What if you want a change in one applet to affect the other applets in some way?
The best way to do this is to use the applet context to get to different applets on the same page. You've already seen the use of the getAppletContext() method for several other uses; you can also use it to get hold of the other applets on the page. For example, to call a method called sendMessage() on all the applets on a page (including the current applet), use the getApplets() method and a for loop that looks something like this:
for (Enumeration e = getAppletContext().getApplets();

        e.hasMoreElements();) {

     Applet current = (Applet)(e.nextElement());

     current.sendMessage();

}
The getApplets() method returns an Enumeration object with a list of the applets on the page. Iterating over the Enumeration object in this way enables you to access each element in the Enumeration in turn.
If you want to call a method in a specific applet, it's slightly more complicated. To do this, you give your applets a name and then refer to them by name inside the body of code for that applet.
To give an applet a name, use the NAME parameter in your HTML file:
<P>This applet sends information:

<APPLET CODE="MyApplet.class" WIDTH=100 HEIGHT=150

    NAME="sender"> </APPLET>

<P>This applet receives information from the sender:

<APPLET CODE="MyApplet.class" WIDTH=100 HEIGHT=150

    NAME="receiver"> </APPLET>
To get a reference to another applet on the same page, use the getApplet() method from the applet context with the name of that applet. This gives you a reference to the applet of that name. You can then refer to that applet as if it were just another object: call methods, set its instance variables, and so on:
// get ahold of the receiver applet

Applet receiver = getAppletContext().getApplet("receiver");

// tell it to update itself.

reciever.update(text, value);
In this example, you use the getApplet() method to get a reference to the applet with the name receiver. Given that reference, you can then call methods in that applet as if it were just another object in your own environment. Here, for example, if both applets have an update() method, you can tell receiver to update itself by using the information the current applet has.
Naming your applets and then referring to them by using the methods described in this section enables your applets to communicate and stay in sync with each other, providing uniform behavior for all the applets on your page.

Summary

Congratulations! Take a deep breath—you're finished with Week 2. This week has been full of useful information about creating applets and using the Java AWT classes to display, draw, animate, process input, and create fully fledged interfaces in your applets.
Today, you finished exploring applets and the AWT by learning about three concepts.
First, you learned about windows, frames, menus, and dialogs, which enable you to create a framework for your applets—or enable your Java applications to take advantage of applet features.
Second, you had a brief introduction to Java networking through some of the classes in the java.net package. Applet networking includes things as simple as pointing the browser to another page from inside your applet, but can also include retrieving files from the Web by using standard Web protocols (http, ftp, and so on). For more advanced networking capabilities, Java provides basic socket interfaces that can be used to implement many basic network-oriented applets—client-server interactions, chat sessions, and so on.
Finally, you finished up with the tidbits—small features of the Java AWT and of applets that didn't fit anywhere else, including showStatus(), providing information about your applet, and communicating between multiple applets on a single page.

Q&A

Q: When I create popup windows using the appletviewer, they all show up with this big yellow bar that says Warning: applet window. What does this mean?
A: The warning is to tell you (and the users of your applet) that the window being displayed was generated by an applet, and not by the browser itself. This is a security feature to keep an applet programmer from popping up a window that masquerades as a browser window and, for example, asks users for their passwords.

There's nothing you can do to hide or obscure the warning.
Q: What good is having a file dialog box if you can't read or write files from the local file system?
A: Applets often can't read or write from the local file system depending on the browser, but because you can use AWT components in Java applications as well as applets, the file dialog box is also very useful for them.
Q: How can I mimic an HTML form submission in a Java applet?
A: Currently, applets make it difficult to do this. The best (and easiest way) is to use GET notation to get the browser to submit the form contents for you.

HTML forms can be submitted in two ways: by using the GET request, or by using POST. If you use GET, your form information is encoded in the URL itself, something like this:

http://www.blah.com/cgi-bin/myscript?foo=1&bar=2&name=Laura

Because the form input is encoded in the URL, you can write a Java applet to mimic a form, get input from the user, and then construct a new URL object with the form data included on the end. Then just pass that URL to the browser by using getAppletContext().showDocument(), and the browser will submit the form results itself. For simple forms, this is all you need.
Q: How can I do POST form submissions?
A: You'll have to mimic what a browser does to send forms using POST: open a socket to the server and send the data, which looks something like this (the exact format is determined by the HTTP protocol; this is only a subset of it):

POST /cgi-bin/mailto.cgi HTTP/1.0
Content-type: application/x-www-form-urlencoded
Content-length: 36

{your encoded form data here}

If you've done it right, you get the CGI form output back from the server. It's then up to your applet to handle that output properly. Note that if the output is in HTML, there really isn't a way to pass that output to the browser that is running your applet yet. This capability may end up in future Java releases. If you get back a URL, however, you can redirect the browser to that URL.
Q: showStatus() doesn't work in my browser. How can I give my readers status information?
A: As you learned in the section on showStatus(), whether or not a browser supports showStatus() is up to that browser. If you must have status-like behavior in your applet, consider creating a status label in the applet itself that is updated with the information you need to present.
Q: It looks like the openStream() method and the Socket classes implement TCP sockets. Does Java support UPD (datagram) sockets?
A: The JDK 1.0 provides two classes, DatagramSocket and DatagramPacket, which implement UDP sockets. The DatagramSocket class operates similarly to the Socket class. Use instances of DatagramPacket for each packet you send or receive over the socket.

See the API documentation for the java.net package for more information.
Q: I've seen something called applet properties in the Java documentation. What are properties?
A: Properties are features of applets and the applet environment that you can test for and make decisions in your code based on their values. At the time this book is being written, properties are still very new. See the latest Java documentation for more information on properties.

No comments:

Post a Comment