27. listopadu 2001, 00.00 | Stručné seznámení jak v Javě vytvářet aplikace, applety či hybridy. V článku si na konkrétních příkladech vysvětlíme principy, které díky přiloženému ukázkovému souboru můžete ihned vyzkoušet v praxi.
V dnešním článku bych chtěl věnovat tomu jak a jakým způsobem vytvářet
programy v Javě.
Java 2 umožňuje vyvíjet několik druhů programů: aplikace, applety,
hybridy a servelety. Tento článek, ale bude zaměřen pouze na první tři
možnosti.
Aplikace
Aplikace je samostatný program, který se více méně podobá běžnému
programu jaký znáte z Dosu či Windows. Obsahuje minimálně jednu třídu a
je u něho definování metoda main(). Výstupem může být jednak standardní
console či grafické rozhraní.
// myApp.java
class myApp
{
public static void main (String[] args)
{
System.out.println ("welcome\n");
}
}
|
|
Tento kód se zkompiluje javac myApp.java, vytvoří se myApp.class a ten se
spustí java myApp. Poznámka: nefunguje-li vám
kompilace, musíte si nejdříve nastavit cestu do adresáře bin vaší
instalace Java např.
set PATH=C:\JDK1.3\BIN;%PATH%
|
|
Výhoda aplikací spočítá v tom, že se dají velmi dobře spouště či
ladit v příkazovém řádku. A takřka nulové bezpečnostní omezení (až na omezení systémem).
A nevýhoda těžko můžete dát obyčejnému uživateli class či jar soubor a
říci mu, ať si tu aplikaci spustí. Natož ať si ji spustí s nějakým
parametrem,
někteří už / ještě ani nevědí co to je.
Jak již bylo naznačeno java soubor může obsahovat více než jednu třídu.
To se může hodit například, když potřebujete mít v jednou souboru více
aplikací či jednu aplikaci, která lze spouštět ve více způsobech např.
pro ladění.
// multiApp.java
class a
{
public static void main (String[] args)
{
System.out.println ("Class a main method");
System.out.println("No parameters
required!");
}
}
class b
{
public static void main (String [] args)
{
System.out.println ("Class b main method");
System.out.println ("Some parameters
required!");
}
}
|
|
Ten to kód se opět zkompiluje javac multiApp.java. Pozor vytvoří se dva soubory a.class a b.class. Ty se pak dají spustit samostatně java a či java b.
Otázka je jestli to je jedna či dvě aplikace. Tato vlastnost se vcelku dobře
dá použít pro debug, kdy je výhodnější mít jednu třídu ve dvou verzích
umístěnou v jednom souboru. Z příkladu je názorně vidět, že dané třídy
lze pak spouštět různým způsobem (vstupem) a také s různým výstupem.
Applety
Naproti tomu applet je takové aplikace, která se spouští v okně
internetového prohlížeče, který ji ovšem kontroluje. Applet je de
facto součástí stránky prohlížeče jako komponenta. Je mu vymezena velikost i umístění.
Parametry mu jsou zadány staticky ve stránce. Svůj výstup vypisuje do dané
oblasti.
Prohlížeč ho automaticky stahuje a JVM ho okamžitě spouští. Naneštěstí
by mohl applet obsahovat nějaké nepožadované funkce, a tak jsou stanoveny
pro applety striktní omezení, která se dají řešit podepisováním aj.
// myApplet.java
import java.awt.*;
public class myApplet extends java.applet.Applet
{
String msg = "Hello";
public void init ()
{
System.out.println ("init");
String s = getParameter ("message");
if (s != null) msg = s;
}
public void start () {
System.out.println ("start");
}
public void paint (Graphics g)
{
g.drawString (msg, 10, 30); }
public void stop ()
{
System.out.println ("stop");
}
public void destroy () {
System.out.println ("destroy");
}
}
|
|
A pro zobrazení v prohlížeči budeme ještě potřebovat vložit tento kód
do html stránky.
<applet code="myApplet.class" width=250 height=50>
<param name="message" value="message for you!">
</applet> |
|
Hlavní výhodou appletů, je že uživatel nemusí kromě toho, že si otevře
ve svém prohlížeči nějakou stránku, nic dělat. Za to ovšem zaplatí
omezenými možnostmi appletu. Lze říci že další nevýhodou je trochu náročnější ladění oproti aplikaci.
Hybridy
Třetí skupinou jsou hybridní programy, které mohou být jak
samostatnou aplikací tak appletem. Zde je nutno definovat samotnou třídu jako
v appletu, ale navíc se zde v této třídě definuje metoda main(), která se
právě použije při spuštění jako aplikace. Pro ty jež se chtějí tomuto tématu věnovat
více doporučuji podívat se do Java 2 SDK dokumentace na AppletStub a
AppletContext či na samotnou třídu Applet.
Je nutné si uvědomit, že applet nemá stejné možnosti jako aplikace! Takže
tento způsob se spíše hodí, pro napsání appletu a zpětném napsání
aplikace. Pokud by jste zvolili opačný způsob, tak se často dostanete do
problémů.
// hybrid.java
import java.applet.*;
import java.awt.*;
import java.lang.*;
import java.util.*;
import java.awt.event.*;
public class hybrid extends Applet
{
int yAbsPos = 0;
StringBuffer buffer;
String myValuesStr, myColorsStr, myBackgroundColorStr;
Integer myValue, myColor;
Color myBackgroundColor;
public hybrid() {
// default contructor must be defined for old Netscape
} // hybrid - constructor
public hybrid(String args[]) {
if (args.length != 3) return;
myValuesStr = args[0];
myColorsStr = args[1];
myBackgroundColorStr = args[2];
} // hybrid - constructor
private Color decodeColor(String s) {
int val = 0;
try {
if (s.startsWith("0x") || s.startsWith("0X")) {
val = (Integer.valueOf(s.substring(2), 16)).intValue();
} else if (s.startsWith("$")) {
val = (Integer.valueOf(s.substring(1), 16)).intValue();
} else if (s.startsWith("#")) {
val = (new Integer(s.substring(1))).intValue();
} else {
val = (new Integer(s)).intValue();
}
return new Color(val);
} catch (NumberFormatException e) {
addItem("decodeColor Err: " +s);
return null;
}
} // decodeColor
void addItem(String newWord) {
System.out.println(newWord);
// debug
/* buffer = new StringBuffer();
buffer.append(newWord);
yAbsPos += 10;
repaint(); */
} // addItem
public void init() {
buffer = new StringBuffer();
addItem("initializing... ");
} // init
public void start() {
addItem("getting Parameters...");
if (myValuesStr == null) { myValuesStr = getParameter("values"); }
if (myColorsStr == null) { myColorsStr = getParameter("colors"); }
if (myBackgroundColorStr == null) { myBackgroundColorStr = getParameter("background"); }
myBackgroundColor = decodeColor(myBackgroundColorStr);
} // start
public void stop() {
addItem("stopping... ");
} // stop
public void destroy() {
addItem("preparing for unloading...");
} // destroy
public void paint(Graphics g) {
int xPos = 0;
int yPos = 0;
int proc = 0;
double myWidth = getSize().width *.0090;
int xPlus = (int) (getSize().width *.05);
int myHeight = (int) (getSize().height *.20);
double totalCount = 0.0;
// canvas border & background
g.setColor(Color.black);
g.drawRect(0, 0, getSize().width, getSize().height);
if (myBackgroundColorStr == null) { g.setColor(Color.white); }
else { g.setColor(myBackgroundColor); }
g.fillRect(0, 0, getSize().width, getSize().height);
g.setColor(Color.black);
yAbsPos = 5;
// canvas scale
for (int x = 0; x < 6;x++) {
g.drawString(Integer.toString(x *20) +"%", xPlus +(int) (x * 20 * myWidth), (int) (getSize().height *.90));
}
// canvas rectangles
if ((myValuesStr != null) && (myColorsStr != null)) {
StringTokenizer ColorTokens = new StringTokenizer(myColorsStr, ";");
StringTokenizer ValueTokens = new StringTokenizer(myValuesStr, ";");
if (ValueTokens.countTokens() != ColorTokens.countTokens()) {
addItem("Err: value\'s count is different from color\'s count");
} else {
while (ValueTokens.hasMoreTokens()) {
totalCount = totalCount + (new Double((ValueTokens.nextToken()).trim())).doubleValue();
}
ValueTokens = new StringTokenizer(myValuesStr, ";");
while (ValueTokens.hasMoreTokens()) {
proc = (int) ((new Double((ValueTokens.nextToken()).trim())).doubleValue() * 100 / totalCount * myWidth); // float strToDouble
g.setColor(Color.black);
g.drawRect(xPlus +xPos, myHeight, proc, getSize().height - 1 -2*myHeight);
g.setColor(decodeColor((ColorTokens.nextToken()).trim()));
g.fillRect(xPlus +xPos, myHeight, proc, getSize().height - 1 -2*myHeight);
xPos += proc;
}
}
}
// Draw the current string inside the rectangle.
g.setColor(Color.black);
g.drawString(buffer.toString(), 50, 10);
}
public static void main(String args[]) {
if (args.length != 3) {
System.out.println("Parameters needed");
System.exit(255);
}
Frame f = new Frame("Graph application");
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
Applet applet = new hybrid(args); // my contructor
// Applet applet = new hybrid(); // default contructor must be defined for old Netscape
f.add("Center", applet);
applet.init();
applet.start();
f.pack();
f.setSize(new Dimension(400,300));
f.show();
} // main
} // class hybrid
|
|
Kompilací hybrid.java získáme několik souborů class. Nás ovšem zajímá
pouze hybrid.class.
Nejdříve ho můžeme spustit jako program.
java hybrid "5; 3.2; 14; 7.2; 12;" "$00ffff; $ffffff; $00ff00; $ff00ff; $ff0000;"
"$808080"
|
|
A nyní si ho můžeme spustit jako applet.
<applet code="hybrid.class" archive="hybrid.jar" width="95%" height="80%" alt="Your browser understands the <APPLET> tag but isn't running the applet, for some reason.">
<param name="values" value="5; 3.2; 14; 7.2; 12;">
<param name="colors" value="$00ffff; $ffffff; $00ff00; $ff00ff; $ff0000;">
<param name="background" value="$808080">
Your browser is completely ignoring the <APPLET> tag!
</applet>
|
|
Tento přístup má v sobě kombinace výhod i nevýhod předchozích přístupů.
Je pravda, že je z nich asi taky nejsložitější, ale i v některých situacích
se právě tento přístup může hodit.
Zde přikládám zdrojové kódy příkladů.