Programavimas

„Java“ patarimas 142: „JButtonGroup“ stūmimas

„Swing“ turi daug naudingų klasių, kurios palengvina grafinės vartotojo sąsajos (GUI) kūrimą. Tačiau kai kurios iš šių klasių nėra tinkamai įgyvendinamos. Vienas tokios klasės pavyzdžių yra Mygtukų grupė. Šiame straipsnyje paaiškinta, kodėl Mygtukų grupė yra prastai suprojektuotas ir siūlo pakaitinę klasę, JButtonGroup, kuri paveldi iš Mygtukų grupė ir išsprendžia kai kurias jo problemas.

Pastaba: Šio straipsnio šaltinio kodą galite atsisiųsti iš išteklių.

MygtukasGrupės skylės

Štai įprastas „Swing“ GUI kūrimo scenarijus: Kuriate formą, kad surinktumėte duomenis apie elementus, kuriuos kažkas įves į duomenų bazę arba išsaugos faile. Formoje gali būti teksto laukelių, žymės langelių, radijo mygtukų ir kitų valdiklių. Jūs naudojate Mygtukų grupė klasėje sugrupuoti visus radijo mygtukus, kuriuos reikia pasirinkti vieną kartą. Kai formos dizainas bus paruoštas, pradėsite diegti formos duomenis. Jūs susiduriate su radijo mygtukų rinkiniu ir turite žinoti, kuris grupės mygtukas buvo pasirinktas, kad galėtumėte saugoti reikiamą informaciją duomenų bazėje ar faile. Jūs dabar įstrigote. Kodėl? Mygtukų grupė klasė nepateikia nuorodos į šiuo metu grupėje pasirinktą mygtuką.

Mygtukų grupė turi „getSelection“ () metodas, kuris grąžina pasirinkto mygtuko modelį (kaip a MygtukasModelis tipas), o ne pats mygtukas. Dabar tai gali būti gerai, jei galėtumėte gauti mygtuko nuorodą iš jo modelio, bet negalite. MygtukasModelis sąsaja ir jos diegimo klasės neleidžia nuskaityti mygtuko nuorodos iš jos modelio. Tai ką darai? Jūs žiūrite į Mygtukų grupė dokumentus ir žiūrėkite „getActionCommand“ () metodas. Jūs atsimenate, kad jei jūs iš karto instituojate a „JRadio“ mygtukas su Stygos šalia mygtuko rodomam tekstui ir paskambinate „getActionCommand“ () ant mygtuko grįžta konstruktoriaus tekstas. Galite pagalvoti, kad vis tiek galite tęsti kodą, nes net jei neturite mygtuko nuorodos, bent jau turite jo tekstą ir vis tiek žinote pasirinktą mygtuką.

Na, staigmena! Kodas nutrūksta vykdymo metu su „NullPointerException“. Kodėl? Nes „getActionCommand“ () į MygtukasModelis grįžta niekinis. Jei lažintumėtės (kaip ir aš) „getActionCommand“ () duoda tą patį rezultatą, nesvarbu, ar skambinama mygtuku, ar modeliu (taip yra ir su daugelis kiti metodai, pvz isSelected (), isEnabled ()arba „getMnemonic“ ()), tu pralaimėjai. Jei aiškiai neskambinate setActionCommand () mygtuke nenustatėte veiksmo komandos savo modelyje, o getter metodas grąžinamas niekinis modeliui. Tačiau getter metodas daro grąžinkite mygtuko tekstą, kai paspaudžiamas mygtukas. Čia yra „getActionCommand“ () metodas SantraukaMygtukas, paveldėtas visų „Swing“ mygtukų klasių:

 viešoji eilutė getActionCommand () {String ac = getModel (). getActionCommand (); if (ac == null) {ac = getText (); } return ac; } 

Šis neatitikimas nustatant ir gaunant veiksmo komandą yra nepriimtinas. Galite išvengti šios situacijos, jei setText () į SantraukaMygtukas nustato veiksmo komandos modelio mygtuką kaip mygtuko tekstą, kai veiksmo komanda yra nulinė. Juk nebent setActionCommand () yra aiškiai vadinamas su kai kuriais Stygos argumentas (ne null), mygtuko tekstas yra veiksmo komandą laikė pačiu mygtuku. Kodėl modelis turėtų elgtis kitaip?

Kai jūsų kodui reikia nuorodos į šiuo metu pasirinktą mygtuką Mygtukų grupė, turite atlikti šiuos veiksmus, iš kurių nė vienas nereiškia skambinimo „getSelection“ ():

  • Skambinkite „getElements“ () ant Mygtukų grupė, kuris grąžina Surašymas
  • Kartoti per Surašymas norėdami gauti nuorodą į kiekvieną mygtuką
  • Skambinkite isSelected () ant kiekvieno mygtuko, kad nustatytumėte, ar jis pasirinktas
  • Grąžinkite nuorodą į mygtuką, kuris buvo tikras
  • Arba, jei jums reikia veiksmo komandos, paskambinkite „getActionCommand“ () ant mygtuko

Jei tai atrodo daugybė žingsnių, kad gautumėte nuorodą į mygtuką, perskaitykite. aš tikiu Mygtukų grupėįgyvendinimas iš esmės yra neteisingas. Mygtukų grupė išsaugo nuorodą į pasirinkto mygtuko modelį, kai jis iš tikrųjų turėtų išsaugoti nuorodą į patį mygtuką. Be to, nuo „getSelection“ () gauna pasirinkto mygtuko metodą, galite pagalvoti, kad atitinkamas seterio metodas yra setSelection (), bet taip nėra: taip setSelected (). Dabar, setSelected () turi didelę problemą. Jos argumentai yra a MygtukasModelis ir loginis. Jei paskambinsite setSelected () ant Mygtukų grupė ir perduoti mygtuko modelį, kuris nėra grupės narys, ir tiesa kaip argumentai, tada pasirenkamas tas mygtukas, o visi grupės mygtukai tampa nepažymėti. Kitaip tariant, Mygtukų grupė turi galią pasirinkti arba atšaukti bet kurį savo metodui perduotą mygtuką, nors mygtukas neturi nieko bendro su grupe. Toks elgesys atsiranda todėl, kad setSelected () į Mygtukų grupė netikrina, ar MygtukasModelis gauta nuoroda kaip argumentas reiškia mygtuką grupėje. Kadangi metodas vykdo vieną pasirinkimą, jis iš tikrųjų panaikina savo mygtukų pasirinkimą, kad pasirinktų nesusijusius su grupe.

Ši nuostata Mygtukų grupė dokumentacija yra dar įdomesnė:

Programos negalima programiškai išjungti, kad ji būtų „išjungta“, kad būtų išvalyta mygtukų grupė. Norėdami atrodyti kaip „niekas nepasirinktas“, pridėkite nematomą radijo mygtuką prie grupės ir tada programiškai pasirinkite tą mygtuką, kad išjungtumėte visus rodomus radijo mygtukus. Pavyzdžiui, įprastą mygtuką su etikete „nėra“ galima prijungti nematomam radijo mygtukui pasirinkti.

Na, tikrai ne. Galite naudoti bet kurį mygtuką, sėdėdami bet kurioje savo programos vietoje, matydami ar nematydami ir net išjungę. Taip, jūs netgi galite naudoti mygtukų grupę, kad pasirinktumėte išjungtą mygtuką už grupės ribų, ir ji vis tiek panaikins visus jos mygtukus. Norėdami gauti nuorodų į visus grupės mygtukus, turite skambinti juokingai „getElements“ (). Su kuo susiję „elementai“ Mygtukų grupė yra kas spėja. Pavadinimą tikriausiai įkvėpė Surašymas klasės metodai (hasMoreElements () ir nextElement ()), bet „getElements“ () aiškiai turėjo būti įvardyti „getButtons“ (). Mygtukas grupuoja mygtukus, o ne elementus.

Sprendimas: „JButtonGroup“

Dėl visų šių priežasčių norėjau įdiegti naują klasę, kuri pašalintų klaidas Mygtukų grupė ir suteikti vartotojui tam tikrą funkcionalumą ir patogumą. Turėjau nuspręsti, ar klasė turėtų būti nauja klasė, ar paveldėti Mygtukų grupė. Visi ankstesni argumentai siūlo sukurti naują klasę, o ne a Mygtukų grupė poklasis. Tačiau MygtukasModelis sąsajai reikalingas metodas setGroup () kad reikia a Mygtukų grupė argumentas. Nebent buvau pasirengęs atnaujinti ir mygtukų modelius, mano vienintelė galimybė buvo subklasė Mygtukų grupė ir viršija daugumą jos metodų. Kalbėdamas apie MygtukasModelis sąsają, pastebėkite, kad nėra vadinamojo metodo „getGroup“ ().

Vienas kitas klausimas, kurio nepaminėjau, yra tas Mygtukų grupė viduje saugo nuorodas į savo mygtukus a Vektorius. Taigi jis be reikalo sinchronizuojamas Vektoriuskai jis turėtų naudoti „ArrayList“, nes pati klasė nėra saugi siūlams, o „Swing“ bet kokiu atveju yra viengija. Tačiau saugomas kintamasis mygtukus yra deklaruojamas a Vektorius tipo, o ne Sąrašas kaip galima tikėtis gero programavimo stiliaus. Taigi negalėjau iš naujo pritaikyti kintamojo kaip „ArrayList“; ir todėl, kad norėjau paskambinti super.add () ir super.remove (), Negalėjau paslėpti superklasės kintamojo. Taigi atsisakiau šio klausimo.

Aš siūlau klasę JButtonGroup, pagal daugumą „Swing“ klasės pavadinimų. Klasė viršija daugumą metodų Mygtukų grupė ir pateikia papildomus patogumo metodus. Čia saugoma nuoroda į šiuo metu pasirinktą mygtuką, kurį galite gauti naudodami paprastą skambutį „getSelected“ (). Ačiū Mygtukų grupėprastą įgyvendinimą, galėčiau įvardyti savo metodą „getSelected“ (), nuo „getSelection“ () yra metodas, kuris pateikia mygtuko modelį.

Šie yra JButtonGroupmetodus.

Pirma, aš padariau dvi modifikacijas papildyti() metodas: jei mygtukas, kurį norite pridėti, jau yra grupėje, metodas grįžta. Taigi, jūs negalite pridėti mygtuko prie grupės daugiau nei vieną kartą. Su Mygtukų grupė, galite sukurti „JRadio“ mygtukas ir pridėkite jį 10 kartų prie grupės. Skambinama getButtonCount () tada grįš 10. Tai neturėtų atsitikti, todėl neleidžiu dublikatų. Tada, jei pridėtas mygtukas buvo pasirinktas anksčiau, jis tampa pasirinktu mygtuku (tai yra numatytasis elgesys Mygtukų grupė, kas yra pagrįsta, todėl nepaisiau to). pasirinktas mygtukas kintamasis yra nuoroda į šiuo metu pasirinktą grupės mygtuką:

public void add (mygtukas „AbstractButton“) mygtukai. yra (mygtukas)) grįžti; super.add (mygtukas); jei (getSelection () == mygtukas.getModel ()) pasirinktasMygtukas = mygtukas; 

Perkrautas papildyti() metodas prideda visą grupę mygtukų. Tai naudinga, kai masyve saugote mygtukų nuorodas, kad būtų galima apdoroti blokus (t. Y. Nustatyti kraštines, pridėti veiksmų klausytojų ir kt.):

public void add (mygtukai AbstractButton []) {if (mygtukai == null) grįžti; už (int i = 0; i

Šie du metodai pašalina mygtuką arba mygtukų masyvą iš grupės:

public void pašalinti (mygtukas AbstractButton) {if (mygtukas! = null) {if (pasirinktasMygtukas == mygtukas) pasirinktasButton = null; super.iimti (mygtukas); }} public void remove (abstraktus mygtukas [] mygtukai) {if (mygtukai == null) grįžti; už (int i = 0; i

Toliau pirmasis setSelected () metodas leidžia nustatyti mygtuko pasirinkimo būseną perduodant mygtuko nuorodą, o ne jo modelį. Antrasis metodas nepaiso atitinkamo setSelected () į Mygtukų grupė kad įsitikintumėte, jog grupė gali pasirinkti arba atšaukti tik grupei priklausantį mygtuką:

public void setSelected (mygtukas „AbstractButton“, pasirinktas loginis elementas) {if (mygtukas! = null && mygtukai. yra (mygtukas)) {setSelected (mygtukas.getModel (), pasirinktas); jei (getSelection () == mygtukas.getModel ()) pasirinktasMygtukas = mygtukas; }} public void setSelected (ButtonModel model, loginė logika pasirinkta) {AbstractButton mygtukas = getButton (modelis); if (mygtukai.turi (mygtukas)) super.setSelected (modelis, pasirinktas); } 

„getButton“ () metodas pateikia nuorodą į mygtuką, kurio modelis pateiktas. setSelected () naudoja šį metodą, kad gautų mygtuką, kurį reikia pasirinkti atsižvelgiant į jo modelį. Jei metodui perduotas modelis priklauso mygtukui už grupės ribų, niekinis yra grąžinamas. Šis metodas turėtų egzistuoti MygtukasModelis diegimai, bet, deja, nėra:

public AbstractButton getButton (ButtonModel modelis) {Iterator it = mygtukai.iterator (); while (it.hasNext ()) {AbstractButton ab = (AbstractButton) it.next (); jei (ab.getModel () == modelis) grąžina ab; } return null; } 

„getSelected“ () ir isSelected () yra paprasčiausi ir tikriausiai naudingiausi JButtonGroup klasė. „getSelected“ () grąžina nuorodą į pasirinktą mygtuką ir isSelected () perkrauna to paties pavadinimo metodą Mygtukų grupė norėdami paimti mygtuką nuorodą:

public AbstractButton getSelected () {return selectedButton; } public boolean isSelected (mygtukas „AbstractButton“) {grįžimo mygtukas == selectedButton; } 

Šis metodas patikrina, ar mygtukas yra grupės dalis:

viešojoje loginėje reikšmėje yra (mygtukas „AbstractButton“) {grįžimo mygtukai. yra (mygtukas); } 

Jūs galėtumėte tikėtis pavadinto metodo „getButtons“ () a Mygtukų grupė klasė. Jis pateikia nekintamą sąrašą, kuriame pateikiamos nuorodos į grupės mygtukus. Nekintamas sąrašas neleidžia pridėti mygtukų ar juos pašalinti, neatliekant mygtukų grupės metodų. „getElements“ () į Mygtukų grupė turi ne tik visiškai neįkvėptą vardą, bet ir grąžina Surašymas, kuri yra pasenusi klasė, kurios neturėtumėte naudoti. Kolekcijų sistemoje pateikiama viskas, ko reikia norint išvengti išvardijimo. Štai taip „getButtons“ () pateikia nekintamą sąrašą:

public list getButtons () {return Collections.unmodifiableList (mygtukai); } 

Pagerinkite „ButtonGroup“

JButtonGroup klasė siūlo geresnę ir patogesnę „Swing“ alternatyvą Mygtukų grupė klasę, išlaikant visą superklasės funkcionalumą.

Danielis Tofanas yra Niujorko valstijos universiteto Stony Brooko chemijos katedros docentas. Jo darbas apima pagrindinės kurso valdymo sistemos dalies, pritaikytos chemijoje, kūrimą. Jis yra „Sun 2“ sertifikuotas „Java 2“ platformos programuotojas ir turi chemijos mokslų daktaro laipsnį.

Sužinokite daugiau apie šią temą

  • Atsisiųskite prie šio straipsnio pridedamą šaltinio kodą

    //images.techhive.com/downloads/idge/imported/article/jvw/2003/09/jw-javatip142.zip

  • „Sun Microsystems“ „Java Foundation Classes“ pagrindinis puslapis

    //java.sun.com/products/jfc/

  • „Java 2 Platform“, „Standard Edition“ (J2SE) 1.4.2 API dokumentacija

    //java.sun.com/j2se/1.4.2/docs/api/

  • „ButtonGroup“ klasė

    //java.sun.com/j2se/1.4.2/docs/api/javax/swing/ButtonGroup.html

  • Peržiūrėti visus ankstesnius „Java“ patarimai ir pateik savo

    //www.javaworld.com/columns/jw-tips-index.shtml

  • Naršykite AWT / sūpynės skyrius „JavaWorld“s aktuali rodyklė

    //www.javaworld.com/channel_content/jw-awt-index.shtml

  • Naršykite Fondo užsiėmimai skyrius „JavaWorld“s aktuali rodyklė

    //www.javaworld.com/channel_content/jw-foundation-index.shtml

  • Naršykite Vartotojo sąsajos dizainas skyrius „JavaWorld“s aktuali rodyklė

    //www.javaworld.com/channel_content/jw-ui-index.shtml

  • Apsilankykite „JavaWorld“ forume

    //www.javaworld.com/javaforums/ubbthreads.php?Cat=&C=2

  • Prisiregistruokite „JavaWorld“nemokami savaitiniai el. pašto naujienlaiškiai

    //www.javaworld.com/subscribe

Šią istoriją „Java Patarimas 142:„ JButtonGroup “stūmimas“ iš pradžių paskelbė „JavaWorld“.

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