Ohjelmointi

Pavun valmistaminen: Luo uudelleenkäytettäviä JavaBeans-komponentteja

Tässä lyhyessä sarjassa tarkastelemme JavaBeans-ohjelmistokomponenttien kehitystä. Viime kädessä useimpia papuja manipuloidaan pavun kehitysympäristössä; olemme kuitenkin huolissamme vain kehyksen lähdetason näkökohdista. JavaBeans-kehityksen edut - toisin sanoen JavaBeans-spesifikaation mukaisen kehityksen - edut ovat moninkertaiset, muun muassa:

  • Pavut voivat olla helposti manipuloitavissa visuaalisissa kehitysympäristöissä käyttäjien, joiden ei tarvitse olla teknisesti taitavia lähdetason Java-kehityksessä.

  • Normaalin käyttöliittymän ansiosta pavut ovat helposti jaettavissa, mikä mahdollistaa kolmansien osapuolten komponenttien helpomman integroinnin kehitystyöhön.

  • Kehittäjät voivat helposti siirtää projektia varten kehitetyn koodin uudelleenkäytettäväksi komponenttikirjastoksi, johon pääsee käsiksi tulevissa kehitystyössä.

Myrskyn silmä

vuonna

sarjan ensimmäinen osa

, kehitimme kaksi yksinkertaista papua: ei-visuaalisen hälytyspapun ja graafisen vasen- / oikea-nuolipapun. Molempia lisättiin visuaalisesti

mukauttaja

ja

paputiedot

luokat. Tässä kuussa tarjoamissamme pavuissa emme tarjoa räätälöintikohteita; sen sijaan keskitymme käyttämään olemassa olevia papuja ja komponentteja suurempien, parempien papujen luomiseen.

Edellytykset

Kaksiosaisen sarjan jatkeena oletan perehtynyt edellisessä erässä käsiteltyihin kysymyksiin, mukaan lukien täydentävät artikkelit ja lähteet.

Pavut

Tämän sarjan alusta loppuun kehitämme seuraavat pavut:

Hälytyspapu Ei-graafinen papu, joka laukaisee tapahtuman tietyn viiveen jälkeen.
NuoliPapu

Graafinen vasen- / oikea-nuolipapu.

Edistyspapu

Graafinen edistymisnäyttöpapu.

NumeroKenttäPapu

Graafinen numeerinen Tekstikenttä papu rullapainikkeilla. Tämä papu käyttää ArrowBean-papua.

FontChooserBean

Graafinen fontinvalitsinpapu. Tämä papu käyttää NumberFieldBean-papua.

FontSelectorBean

Graafinen fontinvalintapapu, joka näyttää nykyisen fontin ja tarjoaa OK / Peruuta-painikkeet. Tämä papu käyttää FontChooserBean-papua.

FontDialogBean

Graafinen fontinvalitsimen papu, joka avaa kirjasimen valitsimen erillisessä valintaikkunassa. Tämä papu käyttää FontSelectorBean-papua.

Keskustelimme Hälytyspapu ja NuoliPapu pavut yksityiskohtaisesti viime kuussa; tässä jaksossa keskustelemme jäljellä olevista pavuista eri yksityiskohdissa.

Saatat ihmetellä, miksi rakennamme kolme fonttipapua. Lopullinen tavoite on yksinkertaisesti tuottaa fontinvalintapapu, joka avaa fontti-valintaikkunan, kun käyttäjä napsauttaa painiketta. Tämä tehtävä jakautuu hyvin luonnollisesti kolmelle tuottamallemme pavulle: Ensimmäinen on käyttöliittymä fonttivalintaa varten, toinen lisää valintaikkunan ohjausobjektit ja fonttinäytteen ja kolmas tuo esiin painikkeen, joka avaa valintaikkunan ja sisältää perustiedot valintaikkunan käsittelykoodi.

Ilman papuja meidän olisi kehitettävä nämä tuotteet erikoistuneina AWT-komponentteina tai yhtenä monoliittisena luokana; papuja käyttämällä voimme kehittää kolme osaa itsenäisinä papuina, jotka ovat itsestään uudelleenkäytettäviä.

Meidän soveltamisala

Kuten tämän sarjan ensimmäisessä erässä, olemme huolissamme vain näiden luokkien beanismista, emmekä todelliset mutterit ja pultit, jotka saavat ne tikittymään. Tuloksena on, että keskustelemme pavuista luuston muodossa, korostamalla punaisella palaset, joilla on erityistä merkitystä, ja jättämällä muut yksityiskohdat sinun tutkittavaksi vapaa-ajallaasi. Emme myöskään pidä huolta räätälöijistä, jotka käsittelimme riittävän yksityiskohtaisesti keskustelemalla kahdesta ensimmäisestä pavusta.

Jos haluat nähdä pakkotyön pavun takana, tutustu täydelliseen lähdekoodiin.

ProgressBean-pavun rakentaminen

Edistyspapu

on yksinkertainen edistymisnäyttöpapu. Se on mukautettu AWT-komponentti, joka näyttää prosentuaalisen arvon ja graafisen pylväsesityksen tästä arvosta alla olevan kuvan mukaisesti. Se paljastaa kaksi ominaisuutta: nykyisen ja maksimipalkin arvon.

Nykyinen arvo paljastetaan havaittavissa oleva omaisuus. Havaittavat ominaisuudet ovat ominaisuuksia, joiden muutokset voidaan havaita. Tarkkailijat rekisteröidään papuun samalla tavalla kuin tapahtumakuuntelijat, ja heille ilmoitetaan aina, kun ominaisuus muuttuu. Pavun on tehtävä nimenomaisesti havaittavaksi pavun yksittäiset ominaisuudet; minkään pavun ominaisuuksiin ei ole mahdollista havaita muutoksia.

Tämä papu toteutetaan kahdella seuraavalla luokalla:

  • Edistyspapu - Papujen pääluokka

  • ProgressBeanBeanInfo - paputietoluokka

Luokan edistyminenPapu

Edistyspapu class on tärkein papuluokka, yksinkertainen mukautettu AWT-komponentti ja Java-papu.

julkisen luokan ProgressBean laajentaa komponenttia ... 

Tämä papu on kevyt komponentti, joten jatkamme Komponentti sijasta Kangasja anna sopiva maali() menetelmä. Kevyt komponenttikehys on tehokkaampi kuin perinteinen räätälöity komponenttikehys, joka vaatii vähemmän paikallisen ikkunointijärjestelmän resursseja. Komponenttina perimme automaattisesti JavaBeansin valtuuttaman sarjoitettavuuden ja tarjoamme oletusarvoisen no-arg-konstruktorin.

public void setBarground (väri c) ... public Color getBarground () ... julkinen synkronoitu void setMaximum (int m) ... public int getMaximum () ... 

Täällä paljastamme Väri omaisuus baari (näytössä olevan palkin väri) ja int omaisuus maksimi (suurin palkin arvo).

julkinen synkronoitu void setValue (int v) {if (arvo! = v) {arvo = v; maalata uudelleen (); fireValueChange (); }} public int getValue () ... 

int omaisuus arvo on havaittavissa, mikä tarkoittaa, että meidän on ilmoitettava kaikille kiinnostuneille kuuntelijoille aina, kun sen arvo muuttuu. Tätä varten kutsumme meitä fireValueChange () tapa ilmoittaa kuulijoille aina aseta arvo() kutsutaan.

suojatut PropertyChangeSupport-kuuntelijat = uusi PropertyChangeSupport (tämä); public void addPropertyChangeListener (PropertyChangeListener l) {kuuntelijat.addPropertyChangeListener (l); } public void removePropertyChangeListener (PropertyChangeListener l) {kuuntelijat.removePropertyChangeListener (l); } 

Tässä ylläpidetään luetteloa objekteista, jotka on rekisteröity ilmoitettaviksi, kun havaittavissa oleva ominaisuus muuttuu. Käytämme luokkaa PropertyChangeSupport alkaen java.beans paketti tämän luettelon ylläpitämiseksi. Tämän luokan rakentaja vaatii meitä määrittämään papun, josta omaisuuden muutostapahtumat alkavat; tässä tapauksessa se on Tämäja sen tarjoamat menetelmät antavat meille mahdollisuuden ylläpitää luetteloa.

Altistamalla menetelmät addPropertyChangeListener () ja removePropertyChangeListener (), ilmoitamme automaattisesti, että tällä pavulla on havaittavia ominaisuuksia. Emme kuitenkaan ilmoita mikä ominaisuudet ovat havaittavissa. Nämä tiedot on dokumentoitava asianmukaisesti papun kanssa.

suojattu kokonaisluku oValue = uusi kokonaisluku (arvo); suojattu void fireValueChange () {listeners.firePropertyChange ("arvo", oValue, oValue = uusi kokonaisluku (arvo)); } 

Kutsumme tätä menetelmää ilmoittaaksemme kuuntelijoille muutoksistamme arvo omaisuus; käytämme firePropertyChange () luettelomme menetelmä tämän ilmoituksen levittämiseksi. Ensimmäinen parametri on ominaisuuden nimi, jonka on vastattava paljastetun ominaisuuden nimeä; toinen parametri on ominaisuuden vanha arvo; ja kolmas ominaisuus on uusi arvo. PropertyChangeSupport luokka palaa tekemättä mitään, jos vanhat ja uudet arvot ovat samat.

Luokan edistyminenBeanBeanInfo

ProgressBeanBeanInfo luokka yksinkertaisesti kuvaa Edistyspapu papu, peittämällä kaikki perilliset tiedot, jotka haluamme peittää.

Rakentaa NumberFieldBean-papu

Tämä papu toteuttaa yhteisen käyttöliittymäkomponentin, vieritettävän numeron syöttökentän - numeerisen tekstikentän, joka tarjoaa lisäys- ja vähennysnuolia, kuten alla olevassa kuvassa esitetään. Tämä papu tuo esiin tärkeän JavaBeans-konseptin:

papujen ohjelmallinen manipulointi

.

Papujen ohjelmallinen manipulointi viittaa mekanismeihin, jotka JavaBeans tarjoaa ohjelmallisesti papujen luomiseen ja käyttämiseen. Vaikka papuihin on mahdollista päästä käyttämällä tavallista Java-objektin luomista (uusi X ()) ja tyyppivalumekanismit ((Y) x), on suositeltavaa käyttää toimitettuja JavaBeans-mekanismeja, jotta JavaBeans-kehys voidaan laajentaa tulevaisuudessa.

Tämä papu toteutetaan kahdella seuraavalla luokalla:

  • NumeroKenttäPapu - Papujen pääluokka

  • NumeroKenttäBeanBeanInfo - paputietoluokka

Luokan numeroKenttäpapu

NumeroKenttäPapu class, tärkein papuluokka, on AWT-säiliö, joka lisää kolme komponenttia: kaksi NuoliPapu pavut ja a Tekstikenttä. Ohjelmallinen pääsy NuoliPapu luokka vaatii, että käytämme hetki sitten mainitsemiani papujen manipulointimekanismeja.

Nykyinen lukuarvo paljastetaan havaittavana ominaisuutena. Vaikka se on normaali ominaisuus, johon pääsee käsiksi ja jota voidaan käsitellä tavallisten pavunlisämenetelmien avulla, se on myös havaittavissa, joten kuuntelijat voivat rekisteröityä ilmoitettaviksi aina, kun sen arvo muuttuu. Emme laukaise tapahtumaa, kun käyttäjä painaa Return-näppäintä, vaikka se olisi ilmeinen laajennus tähän luokkaan.

public class NumberFieldBean laajentaa Kontti toteuttaa ActionListener ... 

Laajennamme Kontti ja toteuttaa ActionListener saadakseen tapahtumia käyttämistämme pavuista ja AWT-komponenteista. Laajentaminen Kontti perinteisemmän sijasta Paneeli tarkoittaa, että tämä papu, kuten Edistyspapu papu on kevyt komponentti.

public NumberFieldBean () ... 

Papuna meidän on tarjottava julkinen ei-arg-konstruktori. Huomaa, että meidän ei pitäisi tarjota muita rakentajia ohjelmalliseen käyttöön; se olisi vastoin JavaBeans-käyttömekanismia.

kokeile {down = (ArrowBean) Beans.instantiate (getClass () .getClassLoader (), "org.merlin.beans.arrow.ArrowBean"); } catch (Exception ex) {ex.printStackTrace (); } 

Täällä luomme NuoliPapu käyttämällä ohjelmallista pavun instantiation -mekanismia. Emme käytä tavallista Javaa Uusi operaattori; sen sijaan käytämme instantiate () luokan menetelmä Pavut. Määritämme ClassLoader käyttää papuluokan lataamiseen; tässä tapauksessa käytämme omaa ClassLoader ja papuluokan täydellinen pätevyys ("org.merlin.beans.arrow.ArrowBean") ja heitä tuloksena oleva Esine sopivaan luokkaan.

Huomaa, että instantiate () menetelmä voi aiheuttaa useita poikkeuksia (esimerkiksi jos määritettyä papua ei löydy). Saamme yksinkertaisesti kiinni ja näytämme kaikki sellaiset poikkeukset, joita ei muuten pitäisi tapahtua, jos papu on asennettu asianmukaisesti.

add ("East", (Component) Beans.getInstanceOf (down, Component.class)); 

Täällä me heitämme NuoliPapu a Komponentti ja lisää se normaalisti Komponentti. Emme käytä standardia (Komponentti) tyypin valumekanismi, emmekä käytä sitä, että meidän Hälytyspapu on ryhmän alaluokka Komponentti; sen sijaan käytämme getInstanceOf () luokan menetelmä Pavut. Määritämme papun, jonka haluamme heittää, ja Luokka esine, jolle haluamme heittää sen (tässä tapauksessa Komponentti. Luokka).

Vaikka tällä lähestymistavalla ei ole juurikaan järkeä juuri nyt, tulevat JavaBeans-versiot tukevat useista luokkatiedostoista koostuvia papuja sekä papuja, jotka voivat paljastaa itsensä eri puolia eri luokkina. Esimerkiksi papu voi näyttää molemmilta alaluokalta Komponentti ja RemoteObject tarjoamalla kaksi kytkettyä luokkaa: a Komponentti ja a RemoteObject. JavaBeans-tyyppivalumekanismin avulla sopiva papuobjekti voidaan palauttaa automaattisesti, joten pavuilla voi olla ilmeinen moniperintö, vaikka Java ei tue sitä luonnollisesti. Katso lisätietoja "Glasgow" JavaBeans -määrityksestä. (Linkki tähän spesifikaatioon on tämän artikkelin Resurssit-osassa.)

Meidän on käytettävä näitä papujen käyttömekanismeja nyt, jotta voimme siirtyä pavuihimme tuleviin JavaBeans-tekniikoihin ilman ongelmia.

down.setDirection (ArrowBean.LEFT); down.addActionListener (tämä); 

Tässä määritämme NuoliPapu käyttämällä setDirection () omaisuudenhoitaja ja addActionListener () rekisteröintimenetelmä. Voimme käyttää näitä omaisuudenhoitajien ja kuuntelijoiden rekisteröintimenetelmiä juuri luomallemme pavulla; JavaBeans-tyyppivalintaominaisuutta on käytettävä vain, kun käytämme papu-ominaisuutta, joka on peritty toisesta luokasta.

julkinen synkronoitu void setValue (int v) {field.setText (String.valueOf (v)); fireValueChange (getValue ()); } julkinen synkronoitu int getValue () ... 

Täällä paljastamme int omaisuus arvo, mikä on tämän kentän arvo. Tämä ominaisuus on havaittavissa, joten meidän on ilmoitettava kuulijoille aina, kun sitä muutetaan. Teemme tämän soittamalla meille fireValueChange () menetelmä.

public void setColumns (int c) ... public int getColumns () ... public synchronized void setMinimum (int m) ... public int getMinimum () ... public synchronized void setMaximum (int m) ... public int getMaximum () ... julkinen synkronoitu void setStep (int s) ... public int getStep () ... 

Täällä paljastamme int ominaisuudet sarakkeita, vähintään, maksimija askel, jotka ovat vastaavasti sarakkeiden lukumäärä Tekstikenttä, pienimmät ja suurimmat arvot, jotka tämän kentän tulisi pitää, ja määrä, jolla nuolipainikkeiden tulisi muuttaa arvoa. Nämä ominaisuudet eivät ole havaittavissa.

Huomaa, että käytämme synkronointia säikeiden turvallisuuden varmistamiseksi tarvittaessa.

julkinen synkronoitu void actionPerformed (ActionEvent e) {int arvo = getValue (); if (e.getSource () == alas) {if (arvo> pienin) {arvo = (arvo - vaihe> arvo)? minimi: puristin (arvo - askel); setValue (arvo); }} ...