Home arrow Java arrow Page 4 - Deploying Multiple Java Applets as One
JAVA

Deploying Multiple Java Applets as One


In this conclusion to a three-part series covering the three different kinds of deployment frameworks you can use with Java games, you'll learn how to deploy multiple Java applets as if they were all one applet. This article is excerpted from chapter two of Advanced Java Game Programming, written by David Wallace Croft (Apress; ISBN: 1590591232).

Author Info:
By: Apress Publishing
Rating: 3 stars3 stars3 stars3 stars3 stars / 9
April 24, 2008
TABLE OF CONTENTS:
  1. · Deploying Multiple Java Applets as One
  2. · MultiAppletNews
  3. · Lifecycle
  4. · MultiApplet
  5. · CroftSoftCollection

print this article
SEARCH DEVARTICLES

Deploying Multiple Java Applets as One - MultiApplet
(Page 4 of 5 )

 

  package com.croftsoft.core.gui.multi;

  [...]

  import com.croftsoft.core.CroftSoftConstants; 
  import com.croftsoft.core.awt.image.ImageLib;
  import com.croftsoft.core.gui.FullScreenToggler;
  import com.croftsoft.core.gui.LifecycleWindowListener;
  import com.croftsoft.core.lang.NullArgumentException;
  import com.croftsoft.core.lang.Pair;
  import com.croftsoft.core.lang.lifecycle.Lifecycle;

  public class  MultiApplet
    extends JApplet
    implements Lifecycle

  //////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////
  {

The main class,MultiApplet, extends the Swing version of theApplet class,JApplet. It imports a number of other classes from the CroftSoft reusable code library. It implements theLifecycle interface with itsinit(),start(),stop(), anddestroy()methods so that it can be integrated into a genericLifecycle framework container.

  public static final String DEFAULT_NEWS_NAME = "News";

  // 

private final String

appletInfo;

private final Pair [ ]

appletPairs;

private final String

newsName;

private final String

newsHTML;

private final String

newsPage;

The instance variableappletInfo is returned when thegetAppletInfo()method is called. VariablesDEFAULT_NEWS_NAME,newsName,newsHTML, andnewsPageare used to create an instance ofMultiAppletNews.

APairis a convenience class from packagecom.croftsoft.core.langthat I use to hold together a related pair ofStringobjects, usually a name-value pair. I like to use an array ofPairinstead of two separateStringarrays because then I do not have to worry about theString arrays accidentally being of unequal length. In theMultiApplet class, I use thenameto store the short name of a game applet to be displayed on a tab at the top of aJTabbedPane. Thevalueis the class name of the corresponding game applet.

  private JTabbedPane       jTabbedPane;

  private Component         appletComponent;

  private boolean           isStarted;

  private int               index;

  private MultiAppletStub  multiAppletStub;

ThisJAppletsubclass maintains an instance reference to aJTabbedPaneSwing component. TheJTabbedPaneis used to contain your game applets. When the user clicks a tab, a different game is loaded.

TheappletComponentis a reference to the game currently loaded. Note that it is an instance ofComponent, notApplet. The boolean flagisStartedprovides life-cycle state information. Theindexvariable indicates which tab is currently selected. TheMultiAppletStubinstance is used to propagate theAppletContextto the game applets.

  public static void main ( String [ ] args )
  //////////////////////////////////////////////////////////////////////
  {
   
launch(
     CroftSoftConstants.DEFAULT_APPLET_INFO,
      new Pair [ ] {
        new Pair ( "Applet1", "javax.swing.JApplet" ),
        new Pair ( "Applet2", "javax.swing.JApplet" ) },
      DEFAULT_NEWS_NAME,
      ( String ) null,
      CroftSoftConstants.HOME_PAGE,
      "CroftSoft MultiApplet", 
     CroftSoftConstants.FRAME_ICON_FILENAME,
      MultiApplet.class.getClassLoader ( ),
      ( Dimension ) null,
      "Close CroftSoft MultiApplet?" );
  }

You use static methodmain()to test theMultiApplet from the command line. It passes test data to the followinglaunch()method.

  public static void  launch (
    String       appletInfo,
    Pair [ ]     appletPairs,
    String       newsName,
    String       newsHTML,
    String       newsPage,
    String       frameTitle,
    String       frameIconFilename,
    ClassLoader frameIconClassLoader,
    Dimension   frameSize,
    String      shutdownConfirmationPrompt )
  //////////////////////////////////////////////////////////////////////
  {
    JFrame  jFrame = new JFrame ( frameTitle );

    try
    {
      Image  iconImage = ImageLib.loadBufferedImage (
        frameIconFilename, frameIconClassLoader );

      if ( iconImage != null )
      {
        jFrame.setIconImage ( iconImage );
      }
    }
    catch ( Exception  ex )
    {
    }

The staticlaunch()method launches the program when it is not embedded in a web page as an applet. This allows it to be run as an executable JAR desktop application or as a Java Web Start application. It starts by creating a new frame and setting the frame icon image, that little picture at the top left corner of the frame. If it cannot find the image, it ignores it and moves on.

  MultiApplet  multiApplet = new MultiApplet (
    appletInfo, appletPairs, newsName, newsHTML, newsPage );
    jFrame.setContentPane ( multiApplet );

    FullScreenToggler.monitor ( jFrame );

 LifecycleWindowListener.launchFrameAsDesktopApp (
      jFrame,
      new Lifecycle [ ] { multiApplet },
      frameSize,
      shutdownConfirmationPrompt );
  }

It then creates an instance of theMultiApplet and sets it as the content page for the frame. MethodFullScreenToggler.monitor(), described in Chapter 5, is used to allow the user to toggle between windowed and full screen mode. The static convenience methodlaunchFrameAsDesktopAppin classLifecycleWindowListenershows the frame and calls the appropriate lifecycle methods on theMultiAppletinstance when the user activates, deactivates, or closes the window.

  public  MultiApplet (
    String    appletInfo,
    Pair [ ]  appletPairs,
    String    newsName,
    String    newsHTML,
    String    newsPage )
  //////////////////////////////////////////////////////////////////////
  {
    NullArgumentException.check ( this.appletInfo  = appletInfo  );

    NullArgumentException.check ( this.appletPairs = appletPairs );

    NullArgumentException.check ( this.newsName    = newsName    );

    this.newsHTML = newsHTML;

    this.newsPage = newsPage;
  }

The constructor method simply saves references to the constructor arguments for later use in theinit()method.

  public String  getAppletInfo ( )
  //////////////////////////////////////////////////////////////////////
  {
   
return appletInfo;
  }

  public void  init ( )
  //////////////////////////////////////////////////////////////////////
  {
    Container  contentPane = getContentPane ( );

    contentPane.setLayout ( new BorderLayout ( ) );

    jTabbedPane = new JTabbedPane (
      JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT );

    contentPane.add ( jTabbedPane, BorderLayout.CENTER );

Theinit()code makes theJTabbedPanefill the frame. The tabs run along the top and can be scrolled left and right when there are too many to fit in the width of the window. By using the scroll tab layout, you can have a large number of tabs, one for each game, without using up additional screen real estate.

  jTabbedPane.add (
    new MultiAppletNews ( newsHTML, newsPage, this ), newsName );

On the first tab, I put the special component calledMultiAppletNews. I treat this component differently from the others because it downloads a web page from my web site. I do not want it to be destroyed when a user clicks another tab because it would then have to download the web page again when the user comes back to it. For this reason, as documented in the following code, the code treats this particular panel differently from the others.

  for ( int  i = 0; i < appletPairs.length; i++ )
  {
    jTabbedPane.add ( new JPanel ( ), appletPairs [ i ].name );
  }

I then create all the other tabs as labeled with the short names of the games.

  jTabbedPane.addChangeListener (
    new ChangeListener ( )
   
{
      public void  stateChanged ( ChangeEvent  changeEvent )
      {
        handleStateChange ( );
      }
    } );

  multiAppletStub = new MultiAppletStub ( this );
  }

I add aChangeListenerto theJTabbedPaneso that I can tell when a user clicks a different tab. I end the initialization method by creating aMultiAppletStub instance.

  public void start ( )
  //////////////////////////////////////////////////////////////////////
  {
   
multiAppletStub.setActive ( true );

    try
    {
      if ( appletComponent instanceof Applet )
      {
       
( ( Applet ) appletComponent ).start ( );
      }
      else if ( appletComponent instanceof Lifecycle )
      {
       
( ( Lifecycle ) appletComponent ).start ( );
     
}
    }
    catch ( Exception  ex )
    {
     
ex.printStackTrace ( );
    }

    isStarted = true;
  }

Thestart()method ofMultiAppletdelegates to thestart()method of the currentappletComponentif it can determine that it is an instance ofAppletorLifecycle. Note that to be included withinMultiApplet, a game must extendComponentbut it does not have to extendAppletor implementLifecycle. An example of this might be a game where the updates are driven exclusively by user-input events such as mouse clicks instead of a continuously running animation thread.

  public void  stop ( )
  //////////////////////////////////////////////////////////////////////
  {
   
multiAppletStub.setActive ( false );

    try
   
{
      if ( appletComponent instanceof Applet )
      {
        ( ( Applet ) appletComponent ).stop ( );
      }
      else if ( appletComponent instanceof Lifecycle )
      {
       
( ( Lifecycle ) appletComponent ).stop ( );
      }
    }
    catch ( Exception  ex )
    {
     
ex.printStackTrace ( );
    }

    isStarted = false;
  }

  public synchronized void  destroy ( )
  //////////////////////////////////////////////////////////////////////
  {
   
try
    {
      if ( appletComponent instanceof Applet )
      {
        ( ( Applet ) appletComponent ).destroy ( );
      }
      else if ( appletComponent instanceof Lifecycle )
      {
        ( ( Lifecycle ) appletComponent ).destroy ( );
      }
    }
    catch ( Exception  ex )
    {
     
ex.printStackTrace ( );
    }
  }

Thestop()anddestroy()methods are similar. Thestart()andstop()methods mutate theactive state of theMultiAppletStub. These methods are usually called in response to windowing events such as window activated or deactivated, window minimized or maximized, or window closed.

  private void  handleStateChange ( )
  //////////////////////////////////////////////////////////////////////
  {
   
if ( isStarted)
    {
      stop ( );
    }

If the user clicks a different tab and the currently selected game is running, thehandleStateChange()method stops it.

  if ( index > 0 )
  {
    jTabbedPane.setComponentAt ( index, new JPanel ( ) );

    destroy ( );

    appletComponent = null;

    System.gc ( );
  }

  index = jTabbedPane.getSelectedIndex ( );

Anindexposition of zero indicates that the tab panel containingMultiAppletNewsis being displayed. Unless the currentindex position is zero, the currentappletComponentis destroyed and all references to it are removed. A garbage collection of system memory is forced at this point to reduce the chances that it will automatically run later and interrupt the animation of the newly selected game. Theindexposition is updated to point to the newly selected tab panel.

  if ( index > 0 )
  {
    try
    {
      appletComponent = ( Component ) Class.forName (
        appletPairs [ index - 1 ].value ).newInstance ( );

If the newindexposition is not zero, the game is loaded into memory using dynamic linking.

  if ( appletComponent instanceof Applet )
  {
    ( ( Applet ) appletComponent ).setStub ( multiAppletStub );
  }

  if ( appletComponent instanceof JComponent )
  {
    FullScreenToggler.monitor ( ( JComponent ) appletComponent );
  }

  jTabbedPane.setComponentAt ( index, appletComponent );

If theappletComponentis an instance ofApplet, theAppletStubis set. If it is an instance ofJComponent, we can monitor it for keyboard events that toggle full screen mode. All the dynamically loaded classes must at least extendComponentso that they can be added to theJTabbedPane.

    try
   
{
      if ( appletComponent instanceof Applet )
      {
        ( ( Applet ) appletComponent ).init ( );
      }
      else if ( appletComponent instanceof Lifecycle )
      {
       
( ( Lifecycle ) appletComponent ).init ( );
      }
    }
    catch ( Exception  ex )
    {
     
ex.printStackTrace ( );
    }

    start ( );
  }
  catch ( Exception  ex )
  {
    ex.printStackTrace ( );
  }
 }
}

Theinit()method of the newappletComponentinstance is followed by a call to thestart()method of theMultiApplet. Note that theinit()method of the MultiAppletinitializes theMultiAppletbut itsstart()method initializes theappletComponent.


blog comments powered by Disqus
JAVA ARTICLES

- Java Too Insecure, Says Microsoft Researcher
- Google Beats Oracle in Java Ruling
- Deploying Multiple Java Applets as One
- Deploying Java Applets
- Understanding Deployment Frameworks
- Database Programming in Java Using JDBC
- Extension Interfaces and SAX
- Entities, Handlers and SAX
- Advanced SAX
- Conversions and Java Print Streams
- Formatters and Java Print Streams
- Java Print Streams
- Wildcards, Arrays, and Generics in Java
- Wildcards and Generic Methods in Java
- Finishing the Project: Java Web Development ...

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials