Java Appl Design

 

 

 

Foreword

Resources

Code Listings

Foil Sets

Assignments

Solutions

External Resources

SiteMap

Search

Home

Up ] Thread Base Applet ] Math Class ] String Classes ] Off Screen GC ] JavaApplet Context ] Events ] Networking ] [ Java Appl Design ]

Example on Application Design

The following is an example application that provide a user friendly interface and allow user to view high resolution images taken from Visible Human Project image data.

The NPAC Visible Human Viewer

Source code :

VisibleHuman.java
ImageFrame.java

The NPAC Visible Human Viewer is an JAVA applet, that contain 9 files:

VisibleHuman.java  -- the Main Applet
ImageFrame.java    -- the Popup Image Frame
Picture.java       -- Object contains ImageCanvas and 2 Scroller
ImageSelector.java -- Image Object with a Selection Line
ImageCanvas.java   -- Image Process and Display Object
Scroller.java      -- Motif Look Scroll Bar
Button3D.java      -- Motif Look 3D Button
Panel3D.java       -- Panel with 3D Outlook
Delay.java         -- Delay Interrupt Object

Use the AWT component provided by JAVA is simple. But there are some problems arise when using AWT components:

Component will have different default size in different platforms.
Component will have different look and feel in different platforms.
Some special functions will hard to be achived. eg. Sometimes, you want the action take place when button is pressed. Sometimes, you want it take place after button is released. Sometimes, you want a button has auto-repeat function, .....

I personally believe UI (user interface) is the most important element in commercial application design. If you are planning to write some serious application on JAVA, you will find the components provided in JAVA AWT is not enough. So I spend a lot of time on UI layout , process flow, and component redesign. It makes this program more complex than it should be, but people will like it more.

The Class Hierarchy in NPAC Visible Human Viewer:

Object --- Delay
Applet --- VisibleHuman
Frame  --- ImageFrame
Panel  --- Panel3D -+- Button3D
                    |
                    +- ImageCanvas --- ImageSelector
                    |
                    +- Picture
                    |
                    +- Scroller

In Panel3D class, I put in the concave/convex drawing utility methods. So the child classes will take advantage of these methods and make the concave/convex's color and style follow the same standard in different components.

The Component Hierarchy:

VisibleHuman -+- board ----+- view[3] --+- logo (ImageCanvas)
              |  (Panel3D) |  (Panel3D) |  
              |            |            +- npac (Button3D)
              |            |               
              |            +- view[0] --+- select[0] (ImageSelector)
              |            |  (Panel3D) |  
              |            |            +- tagBtn[0] (Button3D)
              |            |               ("Axial")
              |            +- view[1] --+- select[1] (ImageSelector)
              |            |  (Panel3D) |  
              |            |            +- tagBtn[1] (Button3D)
              |            |               ("Sagittal")
              |            +- view[2] --+- select[2] (ImageSelector)
              |               (Panel3D) |  
              |                         +- tagBtn[2] (Button3D)
              |                            ("Coronal")
              +- panel ----+- resolutions -+- tagBtn[3] (Button3D)
                 (Panel3D) |  (Panel3D)    |  ("Low")
                           |               +- tagBtn[4] (Button3D)
                           |               |  ("Medium")
                           |               +- tagBtn[5] (Button3D)
                           |                  ("High")
                           +- controls -+- adjust ---+- left (Button3D)
                              (Panel3D) |  (Panel3D) |  (triangle)
                                        |            +- right (Button3D)
                                        |               (triangle)
                                        +- slice (Panel3D)
                                        |  (current slice number)
                                        +- load (Button3D)

ImageFrame Component Hierarchy:

ImageFrame -+- picture (Picture)
            |   
            +- controls --+- Quit (Button3D)
               (Panel3D)  |  ("Quit")
                          +- Download (Button3D)
                          |  ("Download")
                          +- Apply (Button3D)
                          |  ("Apply")
                          +- Org (Button3D)
                          |  ("1:1")
                          +- lbScale (Panel3D)
                          |  (current scale)
                          +- sbScale (Scrller)
                             (HORIZONTAL)

ImageCanvas Component Hierarchy:

Picture -+- canvas (ImageCanvas)
         |  (Center)
         +- hScroll (Scroller)
         |  (South, HORIZONTAL)
         +- vScroll (Scroller)
            (East, VERTICAL)

Scroller Component Hierarchy:

Scroller ----+- up (Button3D)
(HORIZONTAL) |  (West, triangle)
             +- down (Button3D)
                (East, triangle)
Scroller ----+- up (Button3D)
(VERTICAL)   |  (North, triangle)
             +- down (Button3D)
                (South, triangle)

Panel3D instance view[3]

The view[3] component contains logo(ImageCanvas) and npac(Button3D) by using BoardLayout.

Source code: intr001.java

You will see the following code in init() method:

    ...
    /* initialize logo and npac */
    ....
    view[3].setLayout(new BorderLayout());
    view[3].add("South", npac);
    view[3].add("Center", logo);
    ...

Panel3D instance view[0]

The view[0] component contains select[0](ImageSelector) and tagBtn[0](Button3D) by using BoardLayout.

Source code: intr002.java

You will see the following code in init() method:

    ...
    /* initialize logo and npac */
    ....
    view[0].setLayout(new BorderLayout());
    view[0].add("South", tagBtn[0]);
    view[0].add("Center", select[0]);
    ...

Panel3D instance view[1]

The view[1] component contains select[1](ImageSelector) and tagBtn[1](Button3D) by using BoardLayout.

Source code: intr003.java

You will see the following code in init() method:

    ...
    /* initialize logo and npac */
    ....
    view[1].setLayout(new BorderLayout());
    view[1].add("South", tagBtn[1]);
    view[1].add("Center", select[1]);
    ...

Panel3D instance view[2]

The view[2] component contains select[2](ImageSelector) and tagBtn[2](Button3D) by using BoardLayout.

Source code: intr004.java

You will see the following code in init() method:

    ...
    /* initialize logo and npac */
    ....
    view[2].setLayout(new BorderLayout());
    view[2].add("South", tagBtn[2]);
    view[2].add("Center", select[2]);
    ...

Panel3D instance board

Now we put view[0], view[1], view[2], and view[3] into board(Panel3D) by using FlowLayout.

Source code: intr005.java

If you click on the buttons, you will find we need some Event control in order to let the buttons and viewport react to Mouse Event caused by user.

    public boolean action(Event ev, Object arg) {
        if (arg == select[0]) {
          /* Select Cutting Line or View on Axial Image */
          switch ( ev.id ) {
            case Event.MOUSE_DOWN : setCurrent(0); break;
            case Event.MOUSE_UP :
            case Event.MOUSE_DRAG : break;
            default: setCurrent(2);
          }
          return true;
        } else if (arg == select[1]) {
          /* Select Cutting Line or View on Sagittal Image */
          switch ( ev.id ) {
            case Event.MOUSE_DOWN : setCurrent(1); break;
            case Event.MOUSE_UP :
            case Event.MOUSE_DRAG : break;
            default: setCurrent(0);
          }
          return true;
        } else if (arg == select[2]) {
          /* Select Cutting Line or View on Coronal Image */
          switch ( ev.id ) {
            case Event.MOUSE_DOWN : setCurrent(2); break;
            case Event.MOUSE_UP :
            case Event.MOUSE_DRAG : break;
            default: setCurrent(1);
          }
          return true;
        } else if (arg == tagBtn[0]) {
          /* Select View on Axial Image */
          setCurrent(2);
          return true;
        } else if (arg == tagBtn[1]) {
          /* Select View on Sagittal Image */
          setCurrent(0);
          return true;
        } else if (arg == tagBtn[2]) {
          /* Select View on Coronal Image */
          setCurrent(1);
          return true;
        }
        return false;
    }

When responding to component's action in action method, we call setCurrent method to set the proper state of buttons and viewports.

    private void setCurrent(int _current) {
        /* Select the current Viewport */
        if ( current == _current ) return;
        int i, k;
        current = _current;
        k = (current+1)%3;
        showStatus("Select "+tagName[k]+" View");
        for (i=0; i<3; i++) { tagBtn[i].setActive(i!="k);" select[i].setMode((i="=k)" ? 1 : 1); select[i].setColor((i="=current)" ? Color.cyan : Color.red); } } 
Panel3D instance board with Event Handler

Source code: intr006.java

Finally, we introduced all the components contained in board and react correctly to Mouse Selection. It would be impossible to cover every single method and component used in Visible Human project. In this example, we can get some idea about how an application is designed and implemented.