Advanced
Java
Services
|
Kommunikation zwischen Applets |
Kommunikation innerhalb einer HTML-Datei
Wiederum mit Hilfe des AppletContextes ist es möglich, daß mehrere Applets in einer HTML-Datei
miteinander daten austauschen. Der AppletContext bietet zwei Methoden, über die ein Applet
Information enthält, ob noch andere Applets im gleichen HTML-file vorhanden sind.
AppletContext | |
Returntyp | Name der Methode |
Applet | getApplet(String name) Finds and returns the applet in the document represented by this applet context with the given name. |
Enumeration | getApplets() Finds all the applets in the document represented by this applet context. |
Und hier der Quelltext des Applets. Die in unserem Zusammenhang wichtigen Stellen sind rot hervorgehoben.
Man sieht, daß die Information über andere Applets in der start()-Methode noch nicht zur Verfügung steht.
Das Applet verwendet eine Klasse JTextArea2, die eine nützliche Erweiterung zur Klasse
JTextArea darstellt. Über die Vorzüge dieser Klasse, siehe
Die Klasse JTextArea2
import java.awt.* ;
import java.util.* ;
import javax.swing.* ;
import java.awt.event.*;
public class NameApplet extends JApplet
{
private JLabel label = new JLabel( getClass().getName() , SwingConstants.CENTER) ;
private JButton infoButton = new JButton("show all Appletnames");
private JButton clearButton = new JButton("clear");
private JPanel southPanel = new JPanel();
private JTextArea2 tear = new JTextArea2();
private JScrollPane sp = new JScrollPane(tear);
private Container conPane = getContentPane();
public void init()
{
initJMenuBar();
initInfoButton();
initMessageArea();
initSouth();
}
public void start()
{
tear.appendln("infos in start:");
Enumeration enum = getAppletContext().getApplets();
while( enum.hasMoreElements() )
{
Object app = enum.nextElement();
tear.appendln( app.getClass().getName() );
}
tear.appendln("-------------------------------------");
}
private void initJMenuBar()
{
JMenuBar jmb = new JMenuBar();
jmb.setLayout( new BorderLayout());
setJMenuBar(jmb);
jmb.add(label);
label.setOpaque(true);
label.setPreferredSize( new Dimension(100,24) ) ;
//label.setBackground( new Color( 240, 240, 200 ) );
}
private void initInfoButton()
{
infoButton.setPreferredSize( new Dimension(100,22) ) ;
infoButton.addActionListener( new InfoHandler() );
conPane.add(infoButton, BorderLayout.NORTH);
}
private void initMessageArea()
{
conPane.add(sp, BorderLayout.CENTER);
}
private void initSouth()
{
southPanel.setLayout( new GridLayout() );
clearButton.addActionListener( new ClearHandler() );
southPanel.add(clearButton);
conPane.add(southPanel, BorderLayout.SOUTH);
}
class InfoHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
tear.appendln("other applets in this file");
tear.appendln("-------------------------------------");
Enumeration enum = getAppletContext().getApplets();
while( enum.hasMoreElements() )
{
Object app = enum.nextElement();
if (app!=NameApplet.this)
tear.appendln( app.getClass().getName() );
}
tear.appendln("-------------------------------------");
java.applet.Applet theApp = getAppletContext().getApplet("InfoApplet");
tear.appendln("and this is my classname:");
tear.appendln(theApp.getClass().getName() );
tear.appendln("-------------------------------------");
tear.setCaretPosition(-1);
}
}
class ClearHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
tear.setText("");
}
}
} // end class
Der im applet-tag vergebene name ist übrigens nicht case-sensitiv, doch sollte man ihn aus
Sicherheitsgründen case-sensitiv verwenden.
Wie aber kann man Methoden aufrufen, die man zusätzlich in einer eigenen Appletklasse eingebaut hat ?
Eine Möglichkeit zeigt das nächste Beispiel. Die drei Applets dieses Beispiels kommunizieren miteinander
auf die folgende Weise: Jedes Applet kann an die anderen Applets ein Rundschreiben versenden, das in
der JTextArea verfaßt werden kann und durch Buttondruck verschickt wird. Dabei ist es nicht entscheidend,
das es sich um JApplets handelt.
Die drei Applets haben eine gemeinsame Oberklasse, die mit entsprechenden Methoden einen Zugriff
auf die gezeigte JTextArea erlaubt. Über eine setText()-Methode kann man direkt in die JTextArea
schreiben. Alle drei Applets erben diese Methode. Die Basisklasse heißt CommunicationApplet
und sieht wie folgt aus. Die wichtigen Stellen sind rot hervorgehoben.
import java.awt.* ;
import java.util.* ;
import javax.swing.* ;
import java.awt.event.*;
public class CommunicationApplet extends JApplet
{
private JLabel label = new JLabel( getClass().getName() , SwingConstants.CENTER) ;
private JButton infoButton = new JButton("info about other Applets");
private JButton clearButton = new JButton("clear");
private JButton sendButton = new JButton("send circular");
private JPanel southPanel = new JPanel();
private JTextArea2 tear = new JTextArea2();
private JScrollPane sp = new JScrollPane(tear);
private Container conPane = getContentPane();
public void init()
{
initJMenuBar();
initInfoButton();
initMessageArea();
initSouth();
}
private void initJMenuBar()
{
JMenuBar jmb = new JMenuBar();
jmb.setLayout( new BorderLayout());
setJMenuBar(jmb);
jmb.add(label);
label.setOpaque(true);
label.setPreferredSize( new Dimension(100,24) ) ;
//label.setBackground( new Color( 240, 240, 200 ) );
}
private void initInfoButton()
{
infoButton.setPreferredSize( new Dimension(100,22) ) ;
infoButton.addActionListener( new InfoHandler() );
conPane.add(infoButton, BorderLayout.NORTH);
}
private void initMessageArea()
{
conPane.add(sp, BorderLayout.CENTER);
}
private void initSouth()
{
southPanel.setLayout( new GridLayout() );
clearButton.addActionListener( new ClearHandler() );
southPanel.add(clearButton);
sendButton.addActionListener( new MessageHandler() );
southPanel.add(sendButton);
conPane.add(southPanel, BorderLayout.SOUTH);
}
public void setText(String msg)
{
tear.setText(msg);
}
public void setTitleBackground(Color col)
{
label.setBackground(col);
}
class InfoHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Enumeration enum = getAppletContext().getApplets();
while( enum.hasMoreElements() )
{
Object app = enum.nextElement();
if (app!=CommunicationApplet.this)
tear.appendln( app.getClass().getName() );
}
tear.appendln("-------------------------------------");
tear.setCaretPosition(-1);
}
}
class ClearHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
tear.setText("");
}
}
class MessageHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Enumeration enum = getAppletContext().getApplets();
String text = tear.getText() ;
tear.setText("");
while( enum.hasMoreElements() )
{
Object app = enum.nextElement();
if ( app instanceof CommunicationApplet && app!=CommunicationApplet.this)
{
((CommunicationApplet)app).setText(text);
tear.appendln("message send: "+ app.getClass().getName() );
}
}
tear.setCaretPosition(-1);
}
}
} // end class
Die drei oben gezeigten Applets entstehen durch Ableitung aus dem CommunicationApplet
import java.awt.* ;
public class CommunicationApplet1 extends CommunicationApplet
{
public void init()
{
super.init();
setTitleBackground( new Color(240, 240, 200) );
}
} // end class
Analog für die beiden anderen Applets.
Kommunikation zwichen Applets über Dateigrenzen hinweg
Nicht selten hat man mehrere Browserfenster geöffnet und eine Kommunikation von Applets in den
verschiedenen Browserinstanzen kann ein interessantes Feature sein. Falls ein Browser für mehrere
seiner Instanzen dieselbe Javalaufzeitumgebung benützt ist das vermittels statischer Daten tatsächlich
möglich. Das folgende bringt die Kerngedanken eines Artikels von Tobias Hill in
http://www.javaworld.com/javatips/jw-javatip101_p.html
Wieder sollen mehrere Applets miteinander kommunizieren. Wir schaffen uns einen Analogon zu den
Methoden getApplet() und getApplets() auf statischer Ebene. Dazu führen wir eine Applettabelle
ein, bei der sich jedes Applet registriert. Applets können mit statischen Methoden auf diese
Tabelle zugreifen und Zeiger auf andere Applets erhalten. Die hier verwendete Appletliste
erweitert diejenige von Tobias Hill um die Methode keys().
import java.util.*;
import java.applet.*;
public class AppletList
{
private static Hashtable applets = new Hashtable();
public static void register(String name, Applet applet)
{
applets.put(name,applet);
}
public static void remove(String name)
{
applets.remove(name);
}
public static Applet getApplet(String name)
{
return (Applet)applets.get(name);
}
public static Enumeration getApplets()
{
return applets.elements();
}
public static Enumeration keys()
{
return applets.keys();
}
public static int size()
{
return applets.size();
}
}
Jedes Applet, das kommunizieren will, registriert sich in der init()-Methode in diese Liste.
Um für die HashTable eine eindeutige ID zu erhalten verwenden wir die hashCode()-Methode. Auf diese
Weise können wir sogar mehrere Instanzen des gleichen Applets unterscheiden
public void init()
{
AppletList.register( getClass().getName() + "_" + hashCode(), this);
// ...
}
Das folgende Beispiel zeigt die Kommunikation. Zwei Applets befinden sich in dieser Datei. Mit dem Link
darunter lassen sich neue Browserfenster öffnen mit jeweils einer Instanz der gleichen Appletklasse.
neues Browserfenster mit Applet öffnen