6. java.AWT paketas: darbas su langais, įvykiais ir meniu
java.awt.event
paketo klasės:
◊ActionEvent
◊AdjustmentEvent
◊ComponentEvent
◊ContainerEvent
◊FocusEvent
◊InputEvent
◊ItemEvent
◊KeyEvent
◊MouseEvent
◊TextEvent
◊WindowEvent
java.awt.event
paketo interfeisai:
◊ActionListener
◊AdjustmentListener
◊ComponentListener
◊ContainerListener
◊FocusListener
◊ItemListener
◊KeyListener
◊MouseListener
◊TextListener
◊WindowListener
java.awt
(awt - Abstract Windowing Toolkit)
paketas yra vienas didžiausių. Jame patalpintos klasės skirtos kurti
vartotojo aplinką. Šiame skyrelyje susipažinsime su langų kūrimo priemonėmis.
Java langai savo funkcionalumu primena jums gerai pažįstamus "Windows" langus.
Šiame pakete taip pat talpinamos klasės skirtos langų, pelės ir klaviatūros
įvykiams apdoroti.
java.awt
pakete taip pat yra standartinių grafikos elementų
piešimo klasės. Garso, vaizdų ir animacijos organizavimas taip pat priskirtini
java.awt
paketui. Neatskiriama šio paketo dalis yra mygtukai,
sąrašai, vėliavėlės ir t.t. Daugelis įskiepių metodų taip pat paveldima iš
java.awt
paketo klasių hierarchijos.
Langų sukūrimas
6-1 paveikslėlis iliustruoja langų klasių hierarchija šios klasės blokų galiojimo pirmumo medį.
6-1 paveikslėlis. Langų klasių hierarchijos medis.
Neskaitant standartinės Object
klasės,
hierarchijos viršuje yra abstrakti Component
klasė.
Abstrakti klasė pasižymi tuo, kad ji negali turėti egzempliorių
(negalima apibrėžti objektus su new operatoriumi)
ir joje yra bent vienas abstraktus metodas.
Component
klasė yra labai plati. Visų jos laukų ir
metodų aprašymą rasite Java specifikacijos
Component skyrelyje. Išvardinsime tik dalį dažniau naudojamų šios klasės metodų,
kurių paskirtis suprantama iš pavadinimo:
add(PopupMenu popup)
,
addComponentListener(ComponentListener l)
,
addKeyListener(KeyListener l)
,
addMouseListener(MouseListener l)
,
addMouseMotionListener(MouseMotionListener l)
,
addMouseWheelListener(MouseWheelListener l)
,
createImage(ImageProducer producer)
,
createImage(int width, int height)
,
disableEvents(long eventsToDisable)
,
enableEvents(long eventsToEnable)
,
getBounds()
,
getCursor()
,
getFont()
,
getFontMetrics(Font font)
,
getGraphics()
,
getHeight()
,
getWidth()
,
imageUpdate(Image img, int infoflags, int x, int y, int w, int h)
,
isEnabled()
,
paint(Graphics g)
,
paintAll(Graphics g)
,
remove(MenuComponent popup)
,
repaint()
,
repaint(long tmilisec, int x, int y, int width, int height)
,
setCursor(Cursor cursor)
,
setEnabled(boolean b)
,
setFont(Font f)
,
setVisible(boolean b)
,
update(Graphics g)
,
Kitos langų klasės būdamos Component
vaikais paveldi visus
jos metodus ir interfeisus. Tai patogu, nes galima įsisavinti
Component
elementų panaudojimą su kuria nors viena jos poklase,
pavyzdžiui
Buttons
(mygtukai) ir kitose poklasėse naudojimas
nieko nesiskirs. Kiek žemiau langų klasių hierarchijoje stovi
Container
klasė. Ji skirta stačiakampėje srityje išdėstyti
atskirus grafinės vartotojo aplinkos elementus (pvz. mygtukus,
išsirenkamuosius sąrašus ir pan.). Su atskirų elementų išdėstymo
būdais galite susipažinti Java specifikacijos
LayoutManager
skyrelyje.
Toliau langų hierarchijoje stovi greta
Panel
ir Window
klasės. Panel
klasę
naudoja Applet
(įskiepių) klasė. Todėl čia jos plačiau neaptarsime.
Window
klasė skirta aukštutinio lygio langui.
Vienas jo vaikų - Frame
langas turi standartinį naudingų laukų ir
metodų sąrašą ir praktiškai dažniausiai naudojamas. Šios klasės egzempliorius
galima inicijuoti su antrašte arba be. Pavyzdžiui
Frame manoRemelis = new Frame(); Frame manoVardinisRemelis = new Frame("Tiesiog langas");
Sukūrus lango egzempliorių dažnai naudinga nurodyti jo dydį.
Pvz.:
manoRemelis.setSize(400,300);
Rėmelio dydis aprašomas nurodant grafinio ekrano taškelių skaičių x
ir y kryptimis. Atkreipkite dėmesį, kad metodas
setSize(int X, int Y)
yra paskelbtas Component
klasėje.
Jei norite nurodyti ne tik dydį, bet ir rėmelio vietą ekrane, naudokite
setLocation(int OX, int OY)
metodą.
Pvz.:
manoRemelis.setLocation(50,50);
Padėties koordinatės nurodo viršutiniojo kairiojo rėmelio taško koordinates. Kompiuteriuose naudojama kiek neįprasta koordinačių sistema. Jos pradžios taškas laikomas kairysis viršutinis ekrano taškelis.
Metodas
setBounds(int OX, int OY, int X, int Y)
apjungia
setLocation(int OX, int OY)
ir
setSize(int X, int Y)
metodus į vieną.
Pvz.:
manoRemelis.setLocation(50,50); manoRemelis.setSize(400,300);
ir
manoRemelis.setBounds(50,50,400,300);
darbo rezultatas bus tas pats. Jeigu nenorite, kad vartotojas keistų jūsų rėmelio dydį, galite panaudoti tokį metodą:
manoRemelis.setResizable(false);
Rėmelį, kaip ir bet kurį langą, galima rodyti ekrane arba paslėpti. Pavyzdžiui, jei norite parodyti manoRemelis rėmelį, užrašykite komandą
manoRemelis.setVisible(true);
Atkreipkite dėmesį, kad nutylimoji rėmelio matomumo reikšmė yra
false ir todėl bent kartą setVisible(true)
turėsite panaudoti. Kiek kitokia show()
metodo paskirtis. Jis
naudojamas perpiešti ekrane išdėstytus langus taip, kad jūsų pasirinktas
langas atsidurtų pačiame viršuje. Jei prieš show()
metodo vykdymą
langas nebuvo matomas, šis metodas padarys rėmelį matomu.
Rėmelis laikinai paslepiamas neatlaisvinant jo užimamų
resursų su metodu hide()
arba setVisible(false)
,
o galutinai sunaikinamas atlaisvinant jo užimamus resursus su metodu
dispose()
.
Apjungiant keletą išvardintų metodų panaudojimą į vieną vietą gausime tokią paprastą vieno rėmelio sukūrimo Java klasę:
6-1 pvz. Paprasto rėmelio sukūrimo Java klasės pavyzdys.import java.awt.*; public class tiesiogRemelis{ public static final void main(String[] Arg){ // Paskelbiame rėmelio egzempliorių Frame manoRemelis = new Frame("Kuklus remelis"); // Nurodome jo vietą ir dydį ekrane manoRemelis.setLocation(50,50); manoRemelis.setSize(400,300); // Padarome rėmelį matomu viršuje kitų langų atžvilgiu manoRemelis.show(); } // main } // tiesiogRemelis
6-2 paveikslėlis iliustruoja sukompiliuotos ir paleistos komandine eilute
java tiesiogRemelis
darbo rezultatą.
6-2 paveikslėlis. Paprasto rėmelio pavyzdys.
Šis rėmelis pasižymės standartinėmis langų savybėmis. Jis turi pavadinimą "kuklus remelis", su pele galėsite keisti jo vietą ir dydį, jis turės standartinius lango paslėpimo ir sunaikinimo mygtukus. Tačiau šio pavyzdžio lango sunaikinimo mygtukas neveiks. Kad sunaikinimo mygtukas atliktų norimus veiksmus reikia numatyti įvykių apdorojimą ir parašyti papildomus įvykių apdorojimo metodus. Apie tai kalbėsime vėliau.
Įvykių delegavimo mechanizmas
Java įvykių apdorojimas organizuojamas interfeisų pagrindu. Kompiuterio periferijos įrenginiai - klaviatūra, pelė - reaguoja į vartotojo veiksmus ir persiunčia ("deleguoja") juos programinei įrangai. Java tai vadinama įvykių delegavimo mechanizmu .
Bet kuris vartotojo veiksmas vadinamas įvykiu ( event ). Įvykių apdorojimas ir sudaro vartotojo interfeiso pagrindą. Skiriami dviejų rūšių įvykiai: aparatūriniai ir semantiniai .
Aparatūriniai įvykiai yra išaukiami vartotojo mechaninių veiksmų. Pavyzdžiui klaviatūros mygtuko paspaudimas, pelės klavišo nuspaudimas, pelės ratuko pasukimas yra aparatūriniai įvykiai. Semantiniai įvykiai remiasi aparatūriniais įvykiais ir priklauso nuo tuo metu kompiuteryje naudojamų programų. Semantinių įvykių pavyzdžiai yra "Save" ar "File" meniu punktų išsirinkimo veiksmai. Aišku, kad atlikti semantinį įvykį, reikia apdoroti aibę paprastesnių įvykių.
Įvykių delegavimo modelyje naudojama ir įvykio šaltinio sąvoka. Šaltiniu gali būti langas, meniu punktas, valdymo mygtukas. Įvykis šiais atvejais generuojamas, kai pasikeičia šių elementų būsena.
Įvykių apdorojimui realizuoti naudojamas "klausymo" ( listener ) mechanizmas. Taigi gauname tokią grandinę: šaltinis generuoja įvykį, kuris yra perduodamas vienam ar keliems "klausytojams". Gavę pranešimą apie įvykį, klausymo metodai atlieka juose numatytus veiksmus ir grąžina valdymą atgal. Pavyzdžiui gana dažnai paspaudus viršutiniame dešiniajame rėmelio kampe patalpintą mygtuką rėmelis yra panaikinamas. Tai reiškia, kad buvo numatytas semantinio įvykio generavimas ir yra realizuotas jo apdorojimas.
Taigi kuriant vartotojo interfeisą yra numatoma grupė elementų, kurie domisi vartotojo veiksmai. Tokie elementai paskelbiami įvairių įvykių klausytojais ( listener ). Jei vartotoja atliko veiksmus generuojančius įvykį, to konkretaus tipo įvykio klausytojai atlieka juose numatytas operacijas, skirtas apdoroti įvykį.
Toliau susipažinsime su įvykių klasėmis ir interfeisais.
Įvykių klasės ir interfeisai
Yra dvi įvykių superklasės. Viena yra
java.util
paketo klasė
EventObject.
Joje yra tik du metodai:
getSource()
ir toString(),
kurie naudojami identifikuoti įvykio šaltinį. Pirmasis metodas grąžina
įvykį generavusį šaltinį, o antrasis šaltinį identifikuoja tekstu.
AWT paketas turi savo įvykių apdorojimo hierarchiją.
Šios hierarchijos viršūnėje yra java.awt
paketo klasė
AWTEvent.
Įvykio tipas nustatomas
getID() metodu.
Ir vienos ir kitos grupės įvykiai naudoja java.awt
paketą
Event.
Joje skirtingo charakterio įvykiams skiriamos atskiros klasės.
Išvardinsime ir trumpai apibūdinsime šias klases.
ActionEvent
klasės įvykiai generuojami nuspaudus mygtuką, pasirinkus meniu punktą ir su pele
išsirinkus sąrašo elementą.
Svarbiausi klasės metodai:
getActionCommand() ir
getSource() (pastarasis paveldėtas
iš java.util.EventObject
klasės).
AdjustmentEvent
klasės įvykius geruoja ekrano perstūmimo slanksniuotė.
Svarbiausi metodai:
getValue() ir
getAdjusttable.
ComponentEvent
klasės įvykiai geruojami aparatūriniu būdu, kai pasikeičia komponentės dydis,
pozicija ir matomumas.
Šios klasės getComponent()
metodas grąžina informaciją apie tai kokioje komponentėje įvyko įvykis.
ContainerEvent klasės įvykiai geruojami aparatūriniu įvykiu papildžius arba pašalinus iš konteinerio kokią nors komponentę. Šios klasės konstruktorius yra
public ContainerEvent(Component source, int id, Component child);
getChild() metodas grąžina nuorodą į komponentę, kuri buvo pridedama arba šalinama iš konteinerio. getContainer() metodas grąžins nuorodą į konteinerį, kuris buvo įvykio šaltinis. FocusEvent klasės aparatūriniu būdu generuojami įvykiai, kai komponentė gavo arba prarado dėmesį. Pavyzdžiui duomenis komponentėje galima įvesti tik tuo atveju, kai į ją atkreiptas dėmesys. Ši klasė turi du konstruktorius:
public FocusEvent(Component source, int id); // ir public FocusEvent(Component source, int id, boolean temporary);
Jei dėmesio perkėlimas yra pastovus (pvz. perėjimas į kitą duomenų laukelį), dėmesys pereina į kitą komponentę. Priešingu atveju laikinai nukreipus dėmesį į kitą veiksmą ir jį atlikus, dėmesys grįžta į komponentę. Pavyzdžiui paslėpus langą ir vėl jį aktyvavus dėmesys grįš į tą komponentę, kuri turėjo dėmesį prieš paslepiant langą.
InputEvent
yra abstrakti klasė. Šios klasės aparatūriniai įvykiai generuojami
nuspaudus arba atleidus klaviatūros bei pelės klavišus. Priklausomai nuo įvykio
šaltinio yra generuojami šios klasės vaikų įvykiai
KeyEvent
arba
MouseEvent.
isShiftDown()
, isControlDown()
, isAltDown()
metodai naudojami nustatyti specialiųjų klavišų būseną.
ItemEvent
klasės semantinio tipo įvykiai generuojami išsirinkus sąrašo elementą,
pakeitus vėliavėlės būseną, pakeitus meniu punktą.
Dažniau naudojami klasės metodai:
getItemSelectable()
ir
getItem().
Pirmasis metodas grąžina nuorodą į objektą, iš kurio buvo generuotas įvykis,
o antrasis komponentę, kurią įvykis pakeitė.
KeyEvent klasės įvykiai generuojami klaviatūros aparatūriniu būdu.
MouseEvent
yra analogiškas KeyEvent
, tik aparatūrinio įvykio šaltinis šiuo
atveju yra atliekami pele vartotojo veiksmai.
TextEvent
klasės semantiniai įvykiai generuojami įvedant tekstą į teksto lauką ar sritį.
Klasės konstruktorius atrodo taip:
source komponentės objektas, kuris generavo šį įvykį.public TextEvent(Object source, int id);
WindowEvent klasės aparatūriniai įvykiai generuojami lango viduje. Klasės konstruktorius yra
source - komponentės objektas (langas), kuris generavo šį įvykį.public WindowEvent(Window source, int id);
Analogiški charakteringų įvykių klasėms ir jų "klausymo" interfeisai.
Šių interfeisų sąraše:
ActionListener,
AdjustmentListener,
ComponentListener,
ContainerListener,
FocusListener,
ItemListener,
KeyListener,
MouseListener,
TextListener,
WindowListener,
trūksta tik InputEvent
aprašymo.
Su įvykių generavimo ir jų apdorojimo praktiniu pavyzdžiu galite susipažinti vartotojo aplinkos užduoties aprašyme.
Rėmelio (Frame) įvykių apdorojimas
Rėmelyje (lange) vykstantys įvykiai yra klasės
WindowEvent
objektai. Kad reaguoti į šios klasės įvykius, pakete java.awt.event
apibrėžtas
WindowListener
interfeisas. Jei savo programoje
paskelbsite, kad kuri nors klasė implementuoja ( implements )
WindowListener
, tai privalėsite realizuoti visus šio
interfeiso metodus. Trumpai charakterizuosime kiekvieną interfeiso metodą:
Kadangi Frame
klasė yra Component
vaikas, ji
paveldi paint(Graphics g)
metodą, skirtą piešti lango komponentes.
Taip pat šioje klasėje galėsime naudotis repaint()
perpiešimo
metodu. bei kitais paveldėtais metodais.
Pateiksime Frame
ir lango įvykių apdorojimo iliustravimo programą,
kuri lango srityje pieš įvykių rėmelio įvykių istoriją.
// Frame ir WindowListener iliustracija import java.awt.*; import java.awt.event.*; import java.util.*; public class LangoIstorija extends Frame implements WindowListener{ // pradiniai parametrai private static Vector istorija = null; public int plotis = 600; public int aukstis = 60; public Font fnt = new Font("TimesRoman", Font.BOLD, 12); // klases konstruktorius public LangoIstorija(){ super("Vaiksmu su langu istorija"); addWindowListener(this); setSize(plotis,aukstis); show(); } // standartines reakcijos i ivyki metodas public void kasAtsitiko(String kas){ istorija.addElement(kas+": "+kada()+", dydis:"+dydis()); // jei truksta vietos, padidiname langa if (aukstis<2*(1+istorija.size())*fnt.getSize()){ aukstis = 2*(1+istorija.size())*fnt.getSize(); setSize(plotis,aukstis); } repaint(); } // laiko ir ekrano dydzio eiluciu gavimo metodai public String kada(){ Date d = new Date(); return d.toString(); } public String dydis(){ Dimension dim = getSize(); return "["+dim.width+","+dim.height+"]"; } // visu WindowListener interfeise reikalaujamu metodu realizacija public void windowOpened(WindowEvent e){ kasAtsitiko("Atidarytas"); } public void windowActivated(WindowEvent e){ kasAtsitiko("Aktyvuotas"); } public void windowIconified(WindowEvent e){ kasAtsitiko("Sutrauktas"); } public void windowDeiconified(WindowEvent e){ kasAtsitiko("Isplestas"); } public void windowDeactivated(WindowEvent e){ plotis = this.getWidth(); // Įsimename einamąjį lango plotį kasAtsitiko("Neaktyvuotas"); } public void windowClosing(WindowEvent e){ dispose(); System.exit(0); } public void windowClosed(WindowEvent e){ } // Nupiesiame lange sukaupta ivykiu istorija public void paint(Graphics g){ g.setFont(fnt); for (int i=0; i<istorija.size(); i++) g.drawString((String)istorija.elementAt(i),fnt.getSize(),2*(1+i)*fnt.getSize()); } // pradinis main metodas public static final void main(String Arg[]){ istorija = new Vector(); LangoIstorija LI = new LangoIstorija(); } }//LangoIstorija
6-1 pvz. Rėmelį ir lango įvykių apdorojimą iliustruojanti Java klasė.
LangoIstorija.java
6-3 paveikslėlis iliustruoja LangoIstorija
darbo rezultatą atlikus
porą dėmesių perkėlimų iš lango į langą ir vieną lango sutraukimą bei išplėtimą.
6-3 paveikslėlis. LangoIstorija darbo rezultato pavyzdys.
Pelės ir klaviatūros įvykių apdorojimas įvykių apdorojimas neparašytas
Dialoginių langų sukūrimas neparašytas