Programmēšana

Java padoms 35: izveidojiet jaunus notikumu veidus Java

Kaut arī JDK 1.1 noteikti ir pilnveidojusi notikumu apstrādi, ieviešot deleģēšanas notikumu modeli, tas neļauj izstrādātājiem viegli izveidot savus notikumu veidus. Šeit aprakstītā pamatprocedūra faktiski ir diezgan vienkārša. Vienkāršības labad es neapspriedīšu notikumu iespējošanas un pasākumu masku jēdzienus. Turklāt jums jāzina, ka notikumi, kas izveidoti, izmantojot šo procedūru, netiks izlikti notikumu rindā un darbosies tikai ar reģistrētiem klausītājiem.

Pašlaik Java kodols sastāv no 12 notikumu veidiem, kas definēti java.awt.events:

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

Tā kā jaunu notikumu veidu izveide nav mazsvarīgs uzdevums, jums jāpārbauda notikumi, kas ir Java pamatdaļa. Ja iespējams, mēģiniet izmantot šos veidus, nevis izveidot jaunus.

Būs reizes, kad būs nepieciešams izstrādāt jaunu notikumu veidu jaunam komponentam. Šīs diskusijas vajadzībām es izmantošu vienkārša komponenta, vedņa paneļa piemēru kā līdzekli, lai parādītu, kā izveidot jaunu notikuma tipu.

Vedņa panelis ievieš vienkāršu vednis interfeiss. Komponents sastāv no kartes paneļa, kuru var uzlabot, izmantojot pogu NEXT. Poga BACK ļauj pāriet uz iepriekšējo paneli. Tiek piedāvātas arī pogas FINISH un CANCEL.

Lai padarītu komponentu elastīgu, es vēlējos nodrošināt pilnīgu kontroli pār visu pogu veiktajām darbībām izstrādātājam, kurš to izmanto. Piemēram, nospiežot pogu NEXT, izstrādātājam vispirms vajadzētu būt iespējai pārbaudīt, vai vajadzīgie dati tika ievadīti pašlaik redzamajā komponentā, pirms pāriet uz nākamo komponentu.

Lai izveidotu savu notikumu veidu, ir pieci galvenie uzdevumi:

  • Izveidojiet notikumu klausītāju

  • Izveidojiet klausītāja adapteri

  • Izveidojiet notikumu klasi

  • Modificēt komponentu

  • Vairāku klausītāju pārvaldīšana

Mēs pārbaudīsim katru no šiem uzdevumiem pēc kārtas un pēc tam saliksim tos visus kopā.

Izveidojiet notikumu klausītāju

Viens no objektu informēšanas veidiem (un to ir daudz), ka ir notikusi noteikta darbība, ir izveidot jaunu notikumu tipu, ko varētu piegādāt reģistrētiem klausītājiem. Vedņa paneļa gadījumā klausītājam jāatbalsta četri dažādi notikumu gadījumi, pa vienam katrai pogai.

Es sāku ar klausītāja saskarnes izveidošanu. Katrai pogai es definēju klausītāja metodi šādi:

importēt java.util.EventListener; publiskā saskarne WizardListener paplašina EventListener {public abstract void nextSelected (WizardEvent e); public abstract void backSelected (WizardEvent e); publisks abstrakts void cancelSelected (WizardEvent e); publiski abstrakts void finishSelected (WizardEvent e); } 

Katrai metodei nepieciešams viens arguments: WizardEvent, kas ir definēts tālāk. Ņemiet vērā, ka interfeiss paplašinās EventListener, ko izmanto, lai identificētu šo saskarni kā AWT klausītāju.

Izveidojiet klausītāja adapteri

Klausītāja adaptera izveide ir izvēles darbība. AWT klausītāja adapteris ir klase, kas nodrošina noklusējuma ieviešanu visām noteiktā klausītāja veida metodēm. Visas adapteru klases java.awt.event pakete nodrošina tukšas metodes, kas neko nedara. Šeit ir domēna adaptera klase WizardListener:

public class WizardAdapter ievieš WizardListener {public void nextSelected (WizardEvent e) {} public void backSelected (WizardEvent e) {} public void cancelSelected (WizardEvent e) {} public void finishSelected (WizardEvent e) {}} 

Rakstot klasi, kurai jābūt vedņa klausītājam, ir iespējams paplašināt WizardAdapter un nodrošina ieviešanu (vai ignorēšanu) tikai tām interesējošajām klausītāju metodēm. Šī ir stingri ērtības klase.

Izveidojiet notikumu klasi

Nākamais solis ir izveidot faktisko Notikums klase šeit: WizardEvent.

importēt java.awt.AWTEvent; publiskā klase WizardEvent pagarina AWTEvent {public static final int WIZARD_FIRST = AWTEvent.RESERVED_ID_MAX + 1; public static final int NEXT_SELECTED = WIZARD_FIRST; public static final int BACK_SELECTED = WIZARD_FIRST + 1; public static final int CANCEL_SELECTED = WIZARD_FIRST + 2; publiskais statiskais fināls FINISH_SELECTED = WIZARD_FIRST + 3; publiskais statiskais fināls WIZARD_LAST = WIZARD_FIRST + 3; public WizardEvent (vedņa avots, int id) {super (avots, id); }} 

Divas konstantes, WIZARD_FIRST un WIZARD_LAST, atzīmējiet iekļaujošo masku klāstu, ko izmanto šī notikumu klase. Ņemiet vērā, ka notikumu ID izmanto RESERVED_ID_MAX klases konstante AWTEvent lai noteiktu ID diapazonu, kas nebūs pretrunā ar notikuma ID vērtībām, kuras noteikusi AWT. Kad tiek pievienoti vairāk AWT komponentu, RESERVED_ID_MAX var palielināties nākotnē.

Pārējās četras konstantes attēlo četrus notikumu ID, no kuriem katrs atbilst citam darbības veidam, kā to nosaka vedņa funkcionalitāte.

Notikuma ID un notikuma avots ir divi vedņa notikumu konstruktora argumenti. Notikuma avotam jābūt tipam Vednis - tas ir komponenta tips, kuram notikums ir definēts. Pamatojums ir tāds, ka tikai vedņa panelis var būt vedņa notikumu avots. Ņemiet vērā, ka WizardEvent klase pagarinās AWTEvent.

Modificēt komponentu

Nākamais solis ir aprīkot mūsu komponentu ar metodēm, kas ļauj reģistrēt un noņemt klausītājus jaunajam notikumam.

Lai notikumu nogādātu klausītājam, parasti tiek izsaukta atbilstošā notikumu klausītāja metode (atkarībā no notikuma maskas). Es varu reģistrēt darbību klausītāju, lai saņemtu darbības notikumus no pogas NEXT un pārsūtītu tos reģistrētiem WizardListener objektiem. The actionPerformed pogas NEXT (vai citu darbību) darbību klausītāja metodi var ieviest šādi:

public void actionPerformed (ActionEvent e) {// nedariet neko, ja neviens klausītājs nav reģistrēts, ja atgriežas (wizardListener == null); WizardEvent w; Vedņa avots = šis; if (e.getSource () == nextButton) {w = jauns WizardEvent (avots, WizardEvent.NEXT_SELECTED); wizardListener.nextSelected (w); } // līdzīgi rīkojieties ar pārējām vedņa pogām} 

Piezīme. Iepriekš minētajā piemērāVednispats panelis ir klausītājs NĀKAMAIS pogu.

Kad tiek nospiesta poga NEXT, jauna WizardEvent tiek izveidots ar atbilstošu avotu un masku, kas atbilst nospiežamajai pogai NEXT.

Piemērā līnija

 wizardListener.nextSelected (w); 

attiecas uz vednisListener objekts, kas ir privāts locekļa mainīgais domēnam Vednis un ir tipa WizardListener. Mēs esam definējuši šo veidu kā pirmo soli jauna komponenta notikuma izveidē.

No pirmā acu uzmetiena šķiet, ka iepriekš minētais kods ierobežo klausītāju skaitu līdz vienam. Privātais mainīgais vednisListener nav masīvs, un tikai viens nextSelected zvans tiek veikts. Lai izskaidrotu, kāpēc iepriekš minētais kods faktiski nenosaka šo ierobežojumu, pārbaudīsim, kā tiek pievienoti klausītāji.

Katram jaunam komponentam, kas ģenerē notikumus (iepriekš definētus vai jaunus), ir jānodrošina divas metodes: viena, lai atbalstītu klausītāja pievienošanu, un otra, lai atbalstītu klausītāja noņemšanu. Gadījumā, ja no Vednis klasē, šīs metodes ir:

 publiski sinhronizēts tukšums addWizardListener (WizardListener l) {wizardListener = WizardEventMulticaster.add (wizardListener, l); } public synchronized void removeWizardListener (WizardListener l) {wizardListener = WizardEventMulticaster.remove (wizardListener, l); } 

Abas metodes izsauc statiskās metodes dalībniekus WizardEventMulticaster.

Vairāku klausītāju pārvaldīšana

Lai gan ir iespējams izmantot a Vector Lai pārvaldītu vairākus klausītājus, JDK 1.1 nosaka īpašu klasi klausītāju saraksta uzturēšanai: AWTEventMulticaster. Viena multicaster instance uztur atsauces uz diviem klausītāja objektiem. Tā kā multicaster ir arī pats klausītājs (tas realizē visas klausītāja saskarnes), katrs no diviem klausītājiem, kurus viņš seko, var būt arī multicasters, tādējādi izveidojot notikumu klausītāju vai multicasters ķēdi:

Ja klausītājs ir arī multicaster, tad tas pārstāv saiti ķēdē. Pretējā gadījumā tas ir tikai klausītājs un tādējādi ir pēdējais ķēdes elements.

Diemžēl nav iespējams vienkārši atkārtoti izmantot AWTEventMulticaster rīkoties ar notikumu multiziņu jauniem notikumu veidiem. Vislabāk, ko var izdarīt, ir pagarināt AWT multicaster, lai gan šī darbība ir diezgan apšaubāma. AWTEventMulticaster satur 56 metodes. No tām 51 metode nodrošina atbalstu 12 notikumu veidiem un tiem atbilstošajiem klausītājiem, kas ir daļa no AWT. Ja jūs apakšklasē AWTEventMulticaster, jūs tos nekad nelietosiet. No atlikušajām piecām metodēm addInternal (EventListener, EventListener), un noņemt (EventListener) nepieciešams pārkodēt. (Es saku, ka pārkodēts, jo AWTEventMulticaster, addInternal ir statiska metode, un tāpēc to nevar pārslogot. Pašlaik man nezināmu iemeslu dēļ noņemt zvana uz addInternal un tas ir jāpārslogo.)

Divas metodes, saglabāt un saveInternal, sniedz atbalstu objektu straumēšanai, un tos var atkārtoti izmantot jaunajā multicaster klasē. Pēdējā metode, kas atbalsta klausītāju, noņem rutīnas, removeInternal, var arī izmantot atkārtoti, ja vien jaunās noņemt un addInternal ir ieviesti.

Vienkāršības labad es dodos uz apakšklasi AWTEventMulticaster, taču ar ļoti nelielu piepūli ir iespējams kodēt noņemt, saglabāt, un saveInternal un ir pilnībā funkcionāls, atsevišķs notikumu multicaster.

Šeit ir notikumu multicaster, kas ieviests, lai to pārvaldītu WizardEvent:

importēt java.awt.AWTEventMulticaster; importēt java.util.EventListener; publiskā klase WizardEventMulticaster paplašina AWTEventMulticaster īsteno WizardListener {aizsargātā WizardEventMulticaster (EventListener a, EventListener b) {super (a, b); } public static WizardListener add (WizardListener a, WizardListener b) {return (WizardListener) addInternal (a, b); } public static WizardListener remove (WizardListener l, WizardListener oldl) {return (WizardListener) removeInternal (l, oldl); } public void nextSelected (WizardEvent e) {// apraides izņēmums šajā gadījumā nekad nenotiks // casting _is_ ir nepieciešams, jo šis multicaster var // apstrādāt vairāk nekā vienu klausītāju, ja (a! = null) ((WizardListener) a). nextSelected (e); if (b! = null) [[WizardListener] b) .nextSelected (e); } public void backSelected (WizardEvent e) {if (a! = null) ((WizardListener) a) .backSelected (e); if (b! = null) [[WizardListener] b) .backSelected (e); } public void cancelSelected (WizardEvent e) {if (a! = null) ((WizardListener) a) .cancelSelected (e); if (b! = null) [[WizardListener] b) .cancelSelected (e); } public void finishSelected (WizardEvent e) {if (a! = null) ((WizardListener) a) .finishSelected (e); if (b! = null) [[WizardListener] b) .finishSelected (e); } aizsargāts statiskais EventListener addInternal (EventListener a, EventListener b) {if (a == null) return b; if (b == null) atgriež a; atgriezt jauno WizardEventMulticaster (a, b); } aizsargāts EventListener noņemt (EventListener oldl) {if (oldl == a) return b; ja (oldl == b) atgriež a; EventListener a2 = removeInternal (a, oldl); EventListener b2 = removeInternal (b, oldl); if (a2 == a && b2 == b) atgrieziet šo; atgriezties addInternal (a2, b2); }} 

Metodes multicaster klasē: pārskats

Pārskatīsim metodes, kas ietilpst iepriekšminētajā multicaster klasē. Konstruktors ir aizsargāts, un, lai iegūtu jaunu WizardEventMulticaster, statiska pievienot (WizardListener, WizardListener) metode ir jāizsauc. Ir nepieciešami divi klausītāji kā argumenti, kas pārstāv divus klausītāju ķēdes posmus:

  • Lai sāktu jaunu ķēdi, kā pirmo argumentu izmantojiet null.

  • Lai pievienotu jaunu klausītāju, izmantojiet esošo klausītāju kā pirmo argumentu un jaunu klausītāju kā otro argumentu.

Tas faktiski ir izdarīts klases kodā Vednis ka mēs jau esam pārbaudījuši.

Vēl viena statiska rutīna ir noņemt (WizardListener, WizardListener). Pirmais arguments ir klausītājs (vai klausītāja multicaster), un otrais ir noņemamais klausītājs.

Lai atbalstītu notikumu izplatīšanos notikumu ķēdē, tika pievienotas četras publiskas, nestacionāras metodes. Katram WizardEvent gadījumā (tas ir, nākamais, atpakaļ, atcelt un pabeigt atlasīto) ir viena metode. Šīs metodes ir jāievieš kopš WizardEventMulticaster īsteno WizardListener, kas savukārt prasa četras metodes.

Kā tas viss darbojas kopā

Apskatīsim, kā multicaster faktiski izmanto Vednis. Pieņemsim, ka tiek konstruēts vedņa objekts un pievienoti trīs klausītāji, izveidojot klausītāju ķēdi.

Sākumā privātais mainīgais vednisListener klases Vednis ir nulle. Tātad, kad tiek veikts zvans WizardEventMulticaster.add (WizardListener, WizardListener), pirmais arguments, vednisListener, ir null un otrais nav (nav jēgas pievienot nulles klausītāju). The pievienot metode savukārt zvana addInternal. Tā kā viens no argumentiem nav derīgs, atgriešanās addInternal ir nulles klausītājs. Atgriešanās izplatās uz pievienot metode, kas atgriež ne-nulles klausītāju addWizardListener metodi. Tur vednisListener mainīgais ir iestatīts, lai jaunais klausītājs tiktu pievienots.

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