Specialeffekter och spelutveckling
i Java(TM) - En "fontförstorarmeny"
med menyvalsbeskrivningar (FontEnlargerMenu)
av Anibal Wainstein
6.2.2 En "fontförstorarmeny"
med menyvalsbeskrivningar (FontEnlargerMenu)
När
jag satt framför datorn och utvecklade den här appleten,
så fick jag ideligen meddelandet "nullpointerexception"
när jag skulle köra den. Det spelade ingen roll
hur mycket jag bankade på tangentbordet eller monitorn.
Det fungerade helt enkelt inte. Efter att ha avverkat två
tangentbord, så såg jag att jag hade skrivit en
av HTML-parametertaggarna som "PARAN" istället
för "PARAM" och det gjorde att appleten inte
kunde läsa parametern. Det var ett löjligt men nästan
omöjligt fel att hitta. Detta visar att även den
bäste kan råka ut för pinsamma fel. Dessutom
visar det också att våld mot datorer lönar
sig, för jag hittade ju felet efter att ha gett den en
omgång, eller hur?
"fontförstorarmenyn"
som vi skall göra nu är en horizontell meny med
ett antal menyval (i form av texter), som ändrar storlek
när besökaren flyttar muspekaren över dem.
När muspekaren pekar på ett av menyvalen så
visas också en kort beskrivning. Skapa en tom fil som
heter "fontenlargermenu.java" och lägg till
appletdeklarationen och de nödvändiga "import"
deklarationerna. Vi börjar med att titta på variabeldeklarationerna:
//"maxitems" får hålla reda på hur
//många menyval som användaren har
//specifierat.
public int maxitems;
//Arrayerna "items", "descriptions" och
//"urls" kommer att användas för att
//lagra menyvalen, dess beskrivningar
//och adresserna.
public String items[],descriptions[],urls[];
public String target;
//Variablerna "normalfont" och
//"mouseoverfont" lagrar fonterna som
//kommer att användas när vi skriver
//ut menyvalen. Metricsvariablerna
//används för att mäta på dessa fonter.
//Variablerna "descriptionfont" och
//"descriptionmetrics" används för
//menyvalbeskrivningstexten.
public Font normalfont,mouseoverfont,descriptionfont;
public FontMetrics normalmetrics,mouseovermetrics;
public FontMetrics descriptionmetrics;
//Följande variabler har kopierats
//från ButtonMenu appleten. Vi behöver
//dem. Vi har också lagt till "textcolor"
//variabeln.
public Image bufferimage;
public Graphics bufferg;
public Color backgroundcolor,textcolor;
public Image backgroundimage=null;
public Dimension d;
//"currentitem" kommer att användas
//för att hålla reda på vilken
//menyval som precis har valts.
public int currentitem=0;
//Variabeln "displaydescription"
//indikerar om beskrivningstexten
//skall skrivas ut.
public boolean displaydescription=false;
Variabeln
"maxitems" får som vanligt hålla reda
på antalet menyval. Arrayerna "items", "descriptions"
och "urls" används för att lagra menyvalstexten,
dess beskrivningar och adresserna. Den här menyn kommer
att använda två fonter för varje menyval,
en heter "normalfont" och används för
att rita ut texten när besökaren inte fifflar med
appleten. När besökaren pekar på ett speciellt
menyval så används fonten "mouseoverfont"
för att rita texten istället. Vi skall ha ännu
en font, "descriptionfont", och den används
när vi skall rita ut beskrivningstexten. Dessa tre fonter
har dessutom var sitt FontMetrics objekt. Nu när vi arbetar
med texter så har vi också en färgvariabel
för att lagra textfärgen, den heter "textcolor".
Den sista variabeln som bör nämnas är "displaydescription",
när den är sann så skall det visas en beskrivningstext
för menyvalet som muspekaren pekar på. Metoden
init() är ganska komplicerad:
public void init()
{
//while-slingan söker igenom hur många
//"item" parametrar det finns.
maxitems=0;
while (getParameter("item"+maxitems)!=null) maxitems++;
items=new String[maxitems];
descriptions=new String[maxitems];
urls=new String[maxitems];
//Parametrarna för varje menyval läses
//in.
for (int i=0; i<maxitems; i++) { items[i]=getParameter("item"+i); descriptions[i]=getParameter("description"+i); urls[i]=getParameter("url"+i); }
//Bakgrundsfärgen och textfärgen läses in.
backgroundcolor=new Color(getIntegerParameter("backgroundcolor",16));
textcolor=new Color(getIntegerParameter("textcolor",16));
//Bakgrundsbilden läses in, det är bara att
//kopiera och klistra in raderna från TextScroller3.
MediaTracker tracker=new MediaTracker(this);
String backimage=getParameter("backgroundimage");
if (backimage!=null &&
(backimage.toUpperCase().indexOf("JPG")>-1 ||
backimage.toUpperCase().indexOf("GIF")>-1))
{
backgroundimage=getImage(getDocumentBase(),backimage);
tracker.addImage(backgroundimage,0);
try {tracker.waitForAll();}
catch(InterruptedException e) {}
}
//Bufferten initieras...
//Klistra in raderna
//från textscroller3 exemplet.
d=size();
bufferimage=createImage(d.width,d.height);
bufferg=bufferimage.getGraphics();
//Följande rader har kopierats från
//TextScroller3 appleten för att
//ta reda på om appletanvändaren
//vill ha fet eller kursiv stil
//på menytexten.
int fonttype=0;
if (getParameter("italic")!=null && getParameter("italic").substring(0,1).equalsIgnoreCase("y"))
fonttype+=Font.ITALIC;
if (getParameter("bold")!=null && getParameter("bold").substring(0,1).equalsIgnoreCase("y"))
fonttype+=Font.BOLD;
//Skapa menyvalfonterna med de parametrar som har
//specifierats. Observera att nu finns det två
//fontsizeparametrar, "normalfontsize" och "mouseroverfontsize".
normalfont=new Font(getParameter("font"),fonttype,getIntegerParameter("normalfontsize",10));
mouseoverfont=new Font(getParameter("font"),fonttype,getIntegerParameter("mouseoverfontsize",10));
//Initiera metricsvariablerna så att
//de kan användas för att mäta fonterna.
bufferg.setFont(normalfont);
normalmetrics=bufferg.getFontMetrics();
bufferg.setFont(mouseoverfont);
mouseovermetrics=bufferg.getFontMetrics();
//För descriptionfonten bestämmer vi
//storleken och typen.
descriptionfont=new Font("Helvetica",Font.PLAIN,12);
bufferg.setFont(descriptionfont);
descriptionmetrics=bufferg.getFontMetrics();
//Targetparametern laddas in...
target=getParameter("target");
}
Till
att börja med så initieras "maxitems".
Här har vi bara klistrat in raderna från ButtonMenu
och ändrat "normalimage" till "item".
Nästa steg är att initiera arrayerna och läsa
in färgerna och bilderna samt att initiera bufferten.
Här kan du också klistra in många av raderna
från TextScroller3 eller ButtonMenu. Efter ett tag när
man har utvecklat många applets så finner man
att man lätt kan återanvända många metoder
och kodrader. Raderna för att ta fram fontstilen klistras
också in. När det gäller fonterna så
skall "normalfont" och "mouseoverfont"
ha samma fontnamn och stil, men de skall ha varsin "fontsize"
parameter. Då kan appletanvändaren specifiera olika
fontstorlekar. Efter det så initieras "normalmetrics"
och "mouseovermetrics" som är FontMetrics-objekten
för de två fonterna. Fonten som används för
beskrivningstexten får vara fast, fontnamnet blir "TimesRoman"
med vanlig stil och storlek 12, den får användaren
inte ändra på (det finns ingen anledning till det
heller). Okej, innan vi fortsätter så hoppas jag
att du kom ihåg att klistra in getIntegerParameter(),
gotoURL() och update() från ButtonMenu appleten.
Metoden paint() ser ut som följer:
public void paint(Graphics g) { if (bufferg!=null) { if (backgroundimage!=null) { bufferg.drawImage(backgroundimage,0,0,this); } else { bufferg.setColor(backgroundcolor); bufferg.fillRect(0,0,d.width,d.height); } //Slingan ser till att alla menyval //ritas ut. for (int i=0; i<maxitems; i++) { bufferg.setColor(textcolor);
//If-satsen undersöker om besökaren
//pekar på menyvalet. Beroende på om
//han/hon gör det eller inte så
//används "mouseovermetrics" eller
//"normalmetrics" för att mäta på
//fonten.
if (currentitem==i)
{
//Följande rad används för att centrera
//menytexten horizontellt.
int dx=(d.width/maxitems-mouseovermetrics.stringWidth(items[i]))/2;
//Följande rad används för att centrera
//knappen vertikalt.
int dy=(d.height-mouseovermetrics.getHeight())/2;
//Besökaren pekar på den här meny-
//valet så därför använder vi
//mouseover fonten.
bufferg.setFont(mouseoverfont);
//Observera att eftersom menyn är en vertikal
//meny så ser vi till att det finns ett
//steg på (d.width/maxitems) innan nästa
//menyval skrivs ut.
bufferg.drawString(items[i],dx+i*d.width/maxitems,dy+mouseovermetrics.getAscent());
}
else
{
//Besökaren pekar INTE på den här meny-
//valet så därför använder vi
//normal fonten.
bufferg.setFont(normalfont);
int dx=(d.width/maxitems-normalmetrics.stringWidth(items[i]))/2;
int dy=(d.height-normalmetrics.getHeight())/2;
bufferg.drawString(items[i],dx+i*d.width/maxitems,dy+normalmetrics.getAscent());
}
}
//Om "displaydescription" är satt,
//så rita ut en beskrivningstext
//för menyvalet besökaren pekar på.
//Skriv ut texten längst ner
//på appletfönstret.
if (displaydescription)
{
bufferg.setColor(textcolor);
bufferg.setFont(descriptionfont);
bufferg.drawString(descriptions[currentitem]
,(d.width-descriptionmetrics.stringWidth(descriptions[currentitem]))/2
,d.height-2);
}
g.drawImage(bufferimage,0,0,this);
}
}
Raderna
som ritar ut bakgrundsbilden har jag klistrat in från
ButtonMenu, men annars ser metoden helt annorlunda ut. For-slingan
ritar ut alla menyval horizontellt. Där inne så
undersöker vi först om "currentitem" pekar
på ett menyval, om den gör det så använder
den "mouseoverfont" för att rita ut texten.
Varje text centreras med hjälp av variablerna "dx"
och "dy". Vi kan lätt få reda på
bredden och höjden på en text med FontMetrics-metoderna
stringWidth() och getHeight(). Vi räknar ut "dx"
och "dy" på liknande sätt som vi gjorde
i ButtonMenu exemplet, fast vi använder istället
bredden och höjden på varje menytext istället.
Observera också att eftersom den här menyn är
horizontell, så adderas termen i*d.width/maxitems till
x-posisitionen för varje text och det leder till att
texterna radas upp i x-led. Om besökaren inte pekar på
ett menyval så används "normalfont" och
"normalmetrics" för att rita ut texten istället.
Slutligen så undersöks om "displaydescription"
är sant så att beskrivningstexten skrivs ut. Den
här texten centreras horizontellt i mitten av appletområdet
och ritas längst ner på appleten med hjälp
av termen (d.height-2). Metoden mouseMove() är inte så
komplicerad:
public boolean mouseMove(Event e, int x, int y)
{
//Här fungerar beräkningen av menyvalet
//nästan exakt som i ButtonMenu, fast vi
//använder "x" och "d.width" istället.
currentitem=x/(d.width/maxitems);
//"displaydescription" måste nu
//sättas så att beskrivningen för det
//valda menyvalet kommer upp.
displaydescription=true;
update(getGraphics());
return true;
}
Det
enda vi gör här är att beräkna "currentitem"
och sätta "displaydescription" till sant. Variabeln
"currentitem" kan sedan användas i paint()
metoden ovan, för att undersöka om ett menyval har
valts. Metoderna mouseExit() och mouseDown() ser ut som följande:
public boolean mouseExit(Event e, int x, int y)
{
//"displaydescription" måste nu
//sättas till falsk.
displaydescription=false;
//Om användaren lämnar appletområdet
//så sätts "currentimage" till -1 så
//att ingen text ser ut att vara förstorad.
currentitem=-1;
update(getGraphics());
return true;
}
public boolean mouseDown(Event e, int x, int y)
{
gotoURL(urls[currentitem],target);
return true;
}
I
mouseExit() så sätts "currentitem" till
-1, dvs den pekar på ingenting. Variabeln "displaydescription"
sätts till falskt, så att beskrivningstexten inte
syns. Den enda som man behöver göra i mouseDown()
är att anropa gotoURL() med adressen till det menyval
som "currentitem" indikerar. Parametrarna för
appleten skulle kunna se ut så här:
<APPLET CODE="fontenlargermenu.class" WIDTH=500 HEIGHT=50> <PARAM name="backgroundcolor" value="000000"> <PARAM name="textcolor" value="00afff"> <PARAM name="backgroundimage" value="background3.jpg"> <PARAM name="font" value="TimesRoman"> <PARAM name="normalfontsize" value="16"> <PARAM name="mouseoverfontsize" value="20"> <PARAM name="italic" value="no"> <PARAM name="bold" value="yes"> <PARAM name="item0" value="Huvudsida"> <PARAM name="item1" value="Om Javahuset"> <PARAM name="item2" value="Kontakta oss"> <PARAM name="item3" value="Applets"> <PARAM name="description0" value="Kom till Javahusets huvudsida."> <PARAM name="description1" value="Här är en beskrivning på vad vi gör."> <PARAM name="description2" value="Skriv ett brev till oss."> <PARAM name="description3" value="Titta på vår appletsamling"> <PARAM name="url0" value="http://www2.passagen.se/javahuset/"> <PARAM name="url1" value="http://www2.passagen.se/javahuset/omjavahuset.html"> <PARAM name="url2" value="http://www2.passagen.se/javahuset/kontaktaoss.html"> <PARAM name="url3" value="http://www2.passagen.se/javahuset/applets.html"> <PARAM name="target" value=""> </APPLET>
Skillnaden
här, gentemot parametrarna i ButtonMenu, är att
vi har lagt in font-parametrar också. Nu är det
dags att titta på appleten, här är FontEnlargerMenu.
Vi
har nu gått igenom alla de nödvändiga kunskaper
som du måste ha för att kunna utveckla proffessionella
applets. Men hittills har du bara ett blått bälte
i appletprogrammering. Nästa kapitel kommer vi att gå
igenom avancerad bildbehandling, som är en teknik som
mycket få Java-programmerare kan, då kommer ditt
bälte att bli svart som natten...
Nästa sida >>
|
 |  |
|