Programiranje

Java Nasvet 35: Ustvarite nove vrste dogodkov v Javi

Čeprav je JDK 1.1 zagotovo poenostavil ravnanje z dogodki z uvedbo modela prenosa dogodkov, razvijalcem ne olajša ustvarjanja lastnih vrst dogodkov. Tukaj opisan osnovni postopek je pravzaprav precej enostaven. Zaradi poenostavitve ne bom razpravljal o konceptih, ki omogočajo prireditve, in o maskah dogodkov. Poleg tega morate vedeti, da dogodki, ustvarjeni s tem postopkom, ne bodo objavljeni v čakalni vrsti dogodkov in bodo delovali samo z registriranimi poslušalci.

Trenutno jedro Java sestavlja 12 vrst dogodkov, opredeljenih v java.awt.events:

  • ActionEvent
  • AdjustmentEvent
  • ComponentEvent
  • ContainerEvent
  • FocusEvent
  • InputEvent
  • ItemEvent
  • KeyEvent
  • MouseEvent
  • PaintEvent
  • TextEvent
  • WindowEvent

Ker je ustvarjanje novih vrst dogodkov netrivialna naloga, morate preučiti dogodke, ki so del jedra Jave. Če je mogoče, poskusite uporabiti te vrste in ne ustvarjati novih.

Vendar bodo časi, ko bo treba razviti novo vrsto dogodka za novo komponento. Za namene te razprave bom uporabil primer preproste komponente, čarovniške plošče, kot sredstvo za prikaz, kako ustvariti nov tip dogodka.

Čarovnikova plošča izvaja preprosto čarovnik vmesnik. Komponenta je sestavljena iz kartice, ki jo lahko napredujete s pomočjo gumba NEXT. Gumb NAZAJ omogoča preklop na prejšnjo ploščo. Na voljo sta tudi gumba FINISH in CANCEL.

Da bi komponento naredil prilagodljivo, sem razvijalcu, ki jo uporablja, želel zagotoviti popoln nadzor nad dejanji, ki jih izvajajo vsi gumbi. Na primer, ko pritisnete gumb NEXT, mora razvijalec najprej preveriti, ali so bili zahtevani podatki vneseni v komponento, ki je trenutno vidna, preden se premakne na naslednjo komponento.

Pri ustvarjanju lastne vrste dogodka obstaja pet glavnih nalog:

  • Ustvarite poslušalca dogodkov

  • Ustvarite vmesnik poslušalca

  • Ustvarite razred dogodka

  • Spremenite komponento

  • Upravljanje več poslušalcev

Vsako od teh nalog bomo preučili po vrsti in jih nato sestavili.

Ustvarite poslušalca dogodkov

Eden od načinov (in obstaja veliko) obveščanja predmetov, da je prišlo do določenega dejanja, je ustvariti nov tip dogodka, ki bi ga lahko dostavili registriranim poslušalcem. V primeru plošče čarovnika mora poslušalec podpirati štiri različne primere dogodkov, po enega za vsak gumb.

Najprej ustvarim vmesnik poslušalca. Za vsak gumb določim način poslušalca na naslednji način:

uvoz java.util.EventListener; javni vmesnik WizardListener razširja EventListener {public abstract void nextSelected (WizardEvent e); javni povzetek void backSelected (WizardEvent e); javni povzetek void cancelSelected (WizardEvent e); javni povzetek void finishSelected (WizardEvent e); } 

Vsaka metoda ima en argument: WizardEvent, ki je opredeljen v nadaljevanju. Upoštevajte, da se vmesnik širi EventListener, ki se uporablja za identifikacijo tega vmesnika kot poslušalca AWT.

Ustvarite vmesnik poslušalca

Ustvarjanje vmesnika za poslušalce je neobvezen korak. V AWT je vmesnik poslušalca razred, ki zagotavlja privzeto izvedbo za vse metode določene vrste poslušalca. Vsi razredi adapterjev v java.awt.event paket vsebujejo prazne metode, ki nič ne naredijo. Tu je razred adapterjev za WizardListener:

javni razred WizardAdapter izvaja WizardListener {public void nextSelected (WizardEvent e) {} public void backSelected (WizardEvent e) {} public void cancelSelected (WizardEvent e) {} public void finishSelected (WizardEvent e) {}} 

Pri pisanju predavanja, ki naj bi poslušalo čarovnika, je mogoče razširiti WizardAdapter in zagotoviti izvajanje (ali razveljavitev) samo tistih metod poslušalca, ki so zanimive. To je izključno priročen razred.

Ustvarite razred dogodka

Naslednji korak je ustvariti dejansko Dogodek razred tukaj: WizardEvent.

import java.awt.AWTEvent; javni razred WizardEvent razširja AWTEvent {public static final int WIZARD_FIRST = AWTEvent.RESERVED_ID_MAX + 1; javni statični končni int NEXT_SELECTED = WIZARD_FIRST; javni statični končni int BACK_SELECTED = WIZARD_FIRST + 1; javni statični končni int CANCEL_SELECTED = WIZARD_FIRST + 2; javni statični končni int FINISH_SELECTED = WIZARD_FIRST + 3; javni statični končni int WIZARD_LAST = WIZARD_FIRST + 3; javni WizardEvent (vir čarovnika, int id) {super (vir, id); }} 

Dve konstanti, WIZARD_FIRST in WIZARD_LAST, označite vključujoč obseg mask, ki jih uporablja ta razred dogodka. Upoštevajte, da ID-ji dogodkov uporabljajo RESERVED_ID_MAX konstanta razreda AWTE Dogodek za določitev obsega ID-jev, ki ne bodo v nasprotju z vrednostmi ID-ja dogodka, ki jih določa AWT. Ko je dodanih več komponent AWT, se RESERVED_ID_MAX se lahko v prihodnosti poveča.

Preostale štiri konstante predstavljajo štiri ID-je dogodkov, od katerih vsak ustreza različni vrsti dejanja, kot jo določa čarovnikova funkcionalnost.

ID dogodka in vir dogodka sta dva argumenta za konstruktor dogodkov čarovnika. Vir dogodka mora biti vrste Čarovnik - to je vrsta komponente, za katero je dogodek definiran. Utemeljitev je, da je vir čarovniških dogodkov lahko le plošča čarovnika. Upoštevajte, da WizardEvent razred se razširi AWTE Dogodek.

Spremenite komponento

Naslednji korak je opremiti našo komponento z metodami, ki ji omogočajo registracijo in odstranitev poslušalcev za nov dogodek.

Če želite poslušalcu dostaviti dogodek, običajno pokličemo ustrezno metodo poslušalca dogodkov (odvisno od maske dogodka). Prisluškovalca dejanj lahko registriram, da prejema akcijske dogodke s tipko NEXT in jih posredujem registriranim WizardListener predmetov. The actionPermed metoda poslušalca dejanj za gumb NEXT (ali druga dejanja) se lahko izvede na naslednji način:

public void actionPerformed (ActionEvent e) {// ne naredi ničesar, če ni registriran noben poslušalec, če (wizardListener == null) return; WizardEvent w; Vir čarovnika = to; if (e.getSource () == nextButton) {w = nov WizardEvent (vir, WizardEvent.NEXT_SELECTED); wizardListener.nextSelected (w); } // na podoben način ravnajte z ostalimi gumbi čarovnika} 

Opomba: V zgornjem primeru jeČarovnikplošča sama je poslušalec za NASLEDNJI .

Ko pritisnete gumb NEXT, se odpre novo WizardEvent je ustvarjen z ustreznim virom in masko, ki ustreza pritisnjenemu gumbu NEXT.

V primeru vrstica

 wizardListener.nextSelected (w); 

se nanaša na wizardListener objekt, ki je spremenljivka zasebnega člana za Čarovnik in je tipa WizardListener. To vrsto smo opredelili kot prvi korak pri ustvarjanju novega sestavnega dogodka.

Na prvi pogled se zdi, da zgornja koda omejuje število poslušalcev na enega. Zasebna spremenljivka wizardListener ni matrika in samo ena nextSelected klic je opravljen. Da razložimo, zakaj zgornja koda dejansko ne predstavlja te omejitve, preučimo, kako so dodani poslušalci.

Vsaka nova komponenta, ki generira dogodke (vnaprej določene ali nove), mora zagotoviti dva načina: enega, ki podpira dodajanje poslušalca, in drugega, ki podpira odstranitev poslušalca. V primeru Čarovnik te metode so:

 javna sinhronizirana praznina addWizardListener (WizardListener l) {wizardListener = WizardEventMulticaster.add (wizardListener, l); } javna sinhronizirana praznina removeWizardListener (WizardListener l) {wizardListener = WizardEventMulticaster.remove (wizardListener, l); } 

Obe metodi pokličeta člane statične metode razreda WizardEventMulticaster.

Upravljanje več poslušalcev

Čeprav je mogoče uporabiti a Vektor za upravljanje več poslušalcev JDK 1.1 določa poseben razred za vzdrževanje seznama poslušalcev: AWTEventMulticaster. En primerek večkastrskega obdrži sklice na dva predmeta poslušalca. Ker je multicaster tudi sam poslušalec (implementira vse vmesnike poslušalcev), je lahko vsak od obeh poslušalcev, ki mu sledi, tudi multicaster in tako ustvari verigo poslušalcev dogodkov ali multicasterjev:

Če je poslušalec tudi večkater, potem predstavlja člen v verigi. Sicer je zgolj poslušalec in je tako zadnji element v verigi.

Na žalost ni mogoče preprosto ponovno uporabiti AWTEventMulticaster za obdelavo večkanalnih dogodkov za nove vrste dogodkov. Najboljše, kar je mogoče storiti, je razširiti večkolesnik AWT, čeprav je ta operacija precej vprašljiva. AWTEventMulticaster vsebuje 56 metod. Od tega 51 metod zagotavlja podporo za 12 vrst dogodkov in ustrezne poslušalce, ki so del AWT. Če podrazred AWTEventMulticaster, jih tako ali tako nikoli ne boste uporabljali. Od preostalih petih metod addInternal (EventListener, EventListener), in odstrani (EventListener) je treba kodirati. (Pravim, da je prekodirano, ker v AWTEventMulticaster, addInternal je statična metoda in je zato ni mogoče preobremeniti. Iz meni trenutno neznanih razlogov, Odstrani pokliče na addInternal in ga je treba preobremeniti.)

Dve metodi, shrani in saveInternal, zagotavljajo podporo za pretakanje predmetov in jih je mogoče ponovno uporabiti v novem razredu multicaster. Zadnja metoda, ki podpira rutine odstranjevanja poslušalca, removeInternal, se lahko ponovno uporabi, pod pogojem, da nove različice Odstrani in addInternal so bili izvedeni.

Zaradi poenostavitve grem v podrazred AWTEventMulticaster, vendar je z zelo malo truda mogoče kodirati Odstrani, shrani, in saveInternal in imajo popolnoma funkcionalen samostojni multicaster.

Tukaj je multicaster dogodka, kot je izveden za obdelavo WizardEvent:

uvoz java.awt.AWTEventMulticaster; uvoz java.util.EventListener; javni razred WizardEventMulticaster razširja AWTEventMulticaster izvaja WizardListener {zaščiten WizardEventMulticaster (EventListener a, EventListener b) {super (a, b); } javni statični WizardListener add (WizardListener a, WizardListener b) {return (WizardListener) addInternal (a, b); } javni statični WizardListener odstraniti (WizardListener l, WizardListener oldl) {return (WizardListener) removeInternal (l, oldl); } public void nextSelected (WizardEvent e) {// v tem primeru nikoli ne bo prišlo do izjeme za predvajanje // ulivanje _is_ je potrebno, ker lahko ta multicaster // obravnava več kot enega poslušalca, če (a! = null) ((WizardListener) a). nextSelected (e); if (b! = null) ((WizardListener) b) .nextSelected (e); } javna void backSelected (WizardEvent e) {if (a! = null) ((WizardListener) a) .backSelected (e); if (b! = null) ((WizardListener) b) .backSelected (e); } javna void cancelSelected (WizardEvent e) {if (a! = null) ((WizardListener) a) .cancelSelected (e); if (b! = null) ((WizardListener) b) .cancelSelected (e); } javna praznina finishSelected (WizardEvent e) {if (a! = null) ((WizardListener) a) .finishSelected (e); if (b! = null) ((WizardListener) b) .finishSelected (e); } zaščiten statični EventListener addInternal (EventListener a, EventListener b) {if (a == null) return b; if (b == null) vrne a; vrni nov WizardEventMulticaster (a, b); } zaščiten EventListener odstranite (EventListener oldl) {if (oldl == a) return b; if (oldl == b) vrne a; EventListener a2 = removeInternal (a, oldl); EventListener b2 = removeInternal (b, oldl); če (a2 == a && b2 == b) vrne to; vrni addInternal (a2, b2); }} 

Metode v razredu multicaster: Pregled

Oglejmo si metode, ki so del zgornjega razreda multicaster. Konstruktor je zaščiten in za pridobitev novega WizardEventMulticaster, statična dodaj (WizardListener, WizardListener) mora biti poklicana metoda. Kot argumenta, ki predstavljata dva dela verige poslušalcev, sta dva poslušalca povezana:

  • Če želite začeti novo verigo, uporabite null kot prvi argument.

  • Če želite dodati novega poslušalca, uporabite obstoječega poslušalca kot prvi argument in novega poslušalca kot drugi argument.

Pravzaprav je to storjeno v kodi za razred Čarovnik ki smo jih že preučili.

Druga statična rutina je odstraniti (WizardListener, WizardListener). Prvi argument je poslušalec (ali poslušalec multicaster), drugi pa poslušalec, ki ga je treba odstraniti.

V podporo razširjanju dogodkov skozi verigo dogodkov so bile dodane štiri javne, nestatične metode. Za vsakogar WizardEvent primeru (torej izbrani naslednji, nazaj, preklic in zaključek) obstaja ena metoda. Te metode je treba izvajati od WizardEventMulticaster izvaja WizardListener, ki pa zahteva, da so prisotne štiri metode.

Kako vse skupaj deluje

Zdaj pa preučimo, kako multicaster dejansko uporablja Čarovnik. Predpostavimo, da je zgrajen objekt čarovnika in dodani trije poslušalci, ki ustvarjajo verigo poslušalcev.

Sprva zasebna spremenljivka wizardListener razreda Čarovnik je nič. Torej, ko je poklican WizardEventMulticaster.add (WizardListener, WizardListener), prvi argument, wizardListener, je null, drugi pa ne (ni smiselno dodajati ničelnega poslušalca). The dodajte metoda pa kliče addInternal. Ker je eden od argumentov ničen, je vrnitev addInternal je ne-null poslušalec. Vrnitev se širi v dodajte metoda, ki vrne poslušalca, ki ni null, v addWizardListener metoda. Tam wizardListener spremenljivka je nastavljena na novega poslušalca, ki se doda.

$config[zx-auto] not found$config[zx-overlay] not found