Swing ir daudz noderīgu klašu, kas atvieglo grafiskā lietotāja interfeisa (GUI) izstrādi. Dažas no šīm nodarbībām tomēr netiek labi īstenotas. Viens šādas klases piemērs ir PogaGrupa
. Šajā rakstā ir paskaidrots, kāpēc PogaGrupa
ir slikti izstrādāts un piedāvā aizstājēju klasi, JButtonGroup
, kas manto no PogaGrupa
un novērš dažas tās problēmas.
Piezīme: Šī raksta avota kodu varat lejupielādēt vietnē Resursi.
ButtonGroup caurumi
Šeit ir izplatīts Swing GUI izstrādes scenārijs: veidojat veidlapu, lai apkopotu datus par vienumiem, kurus kāds ievadīs datu bāzē vai saglabās failā. Veidlapā var būt tekstlodziņi, izvēles rūtiņas, pogas un citi logrīki. Jūs izmantojat PogaGrupa
klasē, lai sagrupētu visas radiopogas, kurām nepieciešama viena atlase. Kad veidlapas noformējums ir gatavs, sākat ieviest veidlapas datus. Jūs sastopaties ar radio pogu komplektu, un jums jāzina, kura grupas poga tika izvēlēta, lai jūs varētu saglabāt atbilstošo informāciju datu bāzē vai failā. Jūs tagad esat iestrēdzis. Kāpēc? The PogaGrupa
klase nedod jums atsauci uz grupā pašlaik izvēlēto pogu.
PogaGrupa
ir getSelection ()
metode, kas atgriež izvēlētās pogas modeli (kā PogaModelis
tips), nevis pati poga. Tagad tas varētu būt labi, ja jūs varētu iegūt pogas atsauci no tā modeļa, bet nevarat. The PogaModelis
interfeiss un tā ieviešanas klases neļauj izgūt pogas atsauci no tā modeļa. Tad ko tu dari? Jūs skatāties PogaGrupa
dokumentāciju un skatīt getActionCommand ()
metodi. Jūs atceraties, ka, ja jūs instantiate a JRadioButton
ar Stīga
blakus pogai parādītajam tekstam un pēc tam zvanāt getActionCommand ()
uz pogas atgriežas konstruktora teksts. Jūs domājat, ka joprojām varat turpināt kodu, jo pat tad, ja jums nav pogas atsauces, jums vismaz ir tā teksts un jūs joprojām zināt izvēlēto pogu.
Nu, pārsteigums! Jūsu kods darbības laikā saplīst ar a NullPointerException
. Kāpēc? Tā kā getActionCommand ()
iekšā PogaModelis
atgriežas nulle
. Ja jūs derēsit (kā es to izdarīju) getActionCommand ()
rada to pašu rezultātu neatkarīgi no tā, vai to izsauc uz pogas vai modeļa (kas notiek ar daudzi citas metodes, piemēram, isSelected ()
, isEnabled ()
vai getMnemonic ()
), tu zaudēji. Ja jūs skaidri nezvanāt setActionCommand ()
uz pogas jūs nenosaka darbības komandu tās modelī, un metode getter atgriežas nulle
modelim. Tomēr getter metode dara atgrieziet pogas tekstu, kad tiek izsaukta poga. Šeit ir getActionCommand ()
metode AbstractButton
, ko mantoja visas Swing pogu klases:
publiskā virkne getActionCommand () {virkne ac = getModel (). getActionCommand (); if (ac == null) {ac = getText (); } atgriezties ac; }
Šī neatbilstība komandas komandas iestatīšanā un iegūšanā nav pieļaujama. Jūs varat izvairīties no šīs situācijas, ja setText ()
iekšā AbstractButton
iestata modeļa darbības komandu pogas tekstā, ja darbības komanda ir nulle. Galu galā, ja vien setActionCommand ()
tiek skaidri saukts ar dažiem Stīga
arguments (nav nulle), pogas teksts ir uzskatīja darbības komandu ar pašu pogu. Kāpēc modelim būtu jāuzvedas savādāk?
Kad kodam ir nepieciešama atsauce uz pašreiz izvēlēto pogu PogaGrupa
, jums ir jāveic šādas darbības, no kurām neviena nav saistīta ar zvanīšanu getSelection ()
:
- Zvaniet
getElements ()
ieslēgtsPogaGrupa
, kas atgriež anUzskaitīšana
- Atkārtot caur
Uzskaitīšana
lai iegūtu atsauci uz katru pogu - Zvaniet
isSelected ()
uz katras pogas, lai noteiktu, vai tā ir atlasīta - Atgrieziet atsauci uz pogu, kas atgriezās kā patiesa
- Vai arī, ja jums nepieciešama darbības komanda, zvaniet
getActionCommand ()
uz pogas
Ja tas izskatās kā daudz darbību, lai tikai iegūtu pogas atsauci, izlasiet to. ES ticu PogaGrupa
īstenošana ir principiāli nepareiza. PogaGrupa
saglabā atsauci uz izvēlētās pogas modeli, kad tai faktiski jāsaglabā atsauce uz pašu pogu. Turklāt kopš getSelection ()
izgūst izvēlētās pogas metodi, jūs domājat, ka atbilstošā iestatītāja metode ir setSelection ()
, bet tā nav: tā ir setSelected ()
. Tagad, setSelected ()
ir liela problēma. Tās argumenti ir: PogaModelis
un būla. Ja piezvani setSelected ()
uz PogaGrupa
un nodot pogas modeli, kas nav grupas dalībnieks, un taisnība
kā argumenti, šī poga kļūst atlasīta, un visas grupas pogas kļūst neatlasītas. Citiem vārdiem sakot, PogaGrupa
ir tiesības atlasīt vai atcelt jebkuru pogu, kas nodota tās metodei, kaut arī pogai nav nekāda sakara ar grupu. Šī uzvedība rodas tāpēc, ka setSelected ()
iekšā PogaGrupa
nepārbauda, vai PogaModelis
atsauce, kas saņemta kā arguments, apzīmē pogu grupā. Tā kā metode nodrošina vienotu izvēli, tā faktiski atceļ savas pogas, lai izvēlētos vienu, kas nav saistīta ar grupu.
Šis noteikums PogaGrupa
dokumentācija ir vēl interesantāka:
Nu nav īsti. Varat izmantot jebkuru pogu, sēžot jebkurā lietojumprogrammas vietā, redzams vai nē, un pat invalīds. Jā, jūs pat varat izmantot pogu grupu, lai ārpus grupas izvēlētos atspējotu pogu, un tā joprojām atcels visas pogas. Lai iegūtu atsauces uz visām grupas pogām, jums jāsauc smieklīgi getElements ()
. Ar ko saistīti "elementi" PogaGrupa
ir kāds minējums. Nosaukumu, iespējams, iedvesmoja Uzskaitīšana
klases metodes (hasMoreElements ()
un nextElement ()
), bet getElements ()
skaidri vajadzēja nosaukt getButtons ()
. Poga grupē pogas, nevis elementus.
Risinājums: JButtonGroup
Visu šo iemeslu dēļ es vēlējos ieviest jaunu klasi, kas novērš kļūdas PogaGrupa
un nodrošina lietotājam zināmu funkcionalitāti un ērtības. Man bija jāizlemj, vai klasei vajadzētu būt jaunai klasei vai mantot PogaGrupa
. Visi iepriekšējie argumenti iesaka izveidot jaunu klasi, nevis a PogaGrupa
apakšklase. Tomēr PogaModelis
saskarnei nepieciešama metode setGroup ()
kas prasa a PogaGrupa
arguments. Ja vien es nebiju gatavs atjaunot arī pogu modeļus, mana vienīgā iespēja bija apakšklase PogaGrupa
un ignorē lielāko daļu tās metožu. Runājot par PogaModelis
saskarni, pamaniet, ka nav metodes, ko sauc getGroup ()
.
Viens cits jautājums, kuru neesmu minējis, ir tāds PogaGrupa
iekšēji saglabā atsauces uz savām pogām a Vector
. Tādējādi tas nevajadzīgi tiek sinhronizēts Vector
kad tas jāizmanto ArrayList
, tā kā klase pati par sevi nav vītņota, un Swing tik un tā ir ar vienu vītni. Tomēr aizsargātais mainīgais pogas
tiek pasludināts par Vector
tips, un ne Saraksts
kā jūs varētu sagaidīt no laba programmēšanas stila. Tādējādi es nevarēju atkārtoti ieviest mainīgo kā ArrayList
; un tāpēc, ka es gribēju piezvanīt super.add ()
un super.remove ()
, Es nevarēju noslēpt superklases mainīgo. Tāpēc es atteicos no šī jautājuma.
Es ierosinu klasi JButtonGroup
, saskaņā ar lielāko daļu Swing klases nosaukumu. Klase ignorē lielāko daļu metožu PogaGrupa
un nodrošina papildu ērtības metodes. Tas saglabā atsauci uz pašlaik izvēlēto pogu, kuru varat iegūt, vienkārši piezvanot uz getSelected ()
. Pateicoties PogaGrupa
slikta ieviešana, es varētu nosaukt savu metodi getSelected ()
, kopš getSelection ()
ir metode, kas atgriež pogas modeli.
Pēc ir JButtonGroup
metodes.
Pirmkārt, es veicu divas modifikācijas pievienot ()
metode: ja pievienojamā poga jau atrodas grupā, metode atgriežas. Tādējādi jūs nevarat pievienot pogu grupai vairāk nekā vienu reizi. Ar PogaGrupa
, varat izveidot JRadioButton
un pievienojiet to grupai 10 reizes. Zvanīšana getButtonCount ()
pēc tam atgriezīsies 10. Tam nevajadzētu notikt, tāpēc es neatļauju dublēt atsauces. Pēc tam, ja pievienotā poga tika izvēlēta iepriekš, tā kļūst par izvēlēto pogu (tā ir noklusējuma uzvedne sistēmā Windows) PogaGrupa
, kas ir saprātīgi, tāpēc es to nepārcēlu). The izvēlēta poga
mainīgais ir atsauce uz pašlaik izvēlēto pogu grupā:
public void add (pogas AbstractButton poga). satur (poga)) atgriešanās; super.add (poga); if (getSelection () == button.getModel ()) selectedButton = poga;
Pārslogota pievienot ()
metode grupai pievieno veselu pogu masīvu. Tas ir noderīgi, ja blokā apstrādājat masīvā glabājat pogu atsauces (t.i., robežu iestatīšana, darbību klausītāju pievienošana utt.):
public void add (AbstractButton [] pogas) {if (pogas == null) atgriežas; par (int i = 0; i
Pogas vai pogu masīvu no grupas noņem no šīm divām metodēm:
public void noņemt (poga AbstractButton) {if (poga! = null) {if (izvēlētaButton == poga) selectedButton = null; super.noņemt (poga); }} public void remove (AbstractButton [] pogas) {if (pogas == null) atgriežas; par (int i = 0; i
Turpmāk pirmais setSelected ()
metode ļauj iestatīt pogas izvēles stāvokli, nododot pogas atsauci, nevis tās modeli. Otrā metode ignorē atbilstošo setSelected ()
iekšā PogaGrupa
lai pārliecinātos, ka grupa var atlasīt vai atcelt tikai pogu, kas pieder grupai:
public void setSelected (poga AbstractButton, izvēlēta būla vērtība) {if (poga! = null && pogas. satur (poga)) {setSelected (button.getModel (), izvēlēts); if (getSelection () == button.getModel ()) selectedButton = poga; }} public void setSelected (ButtonModel model, Boolean selected) {AbstractButton button = getButton (model); ja (pogas. satur (poga)) super.setSelected (modelis, izvēlēts); }
The getButton ()
metode izgūst atsauci uz pogu, kuras modelis ir dots. setSelected ()
izmanto šo metodi, lai izgūtu izvēlēto pogu, ņemot vērā tā modeli. Ja metodei nodotais modelis pieder pogai ārpus grupas, nulle
tiek atgriezta. Šai metodei vajadzētu būt PogaModelis
ieviešana, bet diemžēl tā nav:
public AbstractButton getButton (ButtonModel modelis) {Iterator it = pogas.iterator (); while (it.hasNext ()) {AbstractButton ab = (AbstractButton) it.next (); if (ab.getModel () == modelis) atgriež ab; } return null; }
getSelected ()
un isSelected ()
ir vienkāršākās un, iespējams, visnoderīgākās JButtonGroup
klasē. getSelected ()
atgriež atsauci uz izvēlēto pogu un isSelected ()
operētājsistēmā pārslogo tā paša nosaukuma metodi PogaGrupa
ņemt atsauci uz pogu:
public AbstractButton getSelected () {return selectedButton; } public boolean isSelected (poga AbstractButton) {atgriešanās poga == selectedButton; }
Šī metode pārbauda, vai poga ir daļa no grupas:
public Boolean satur (poga AbstractButton) {atgriešanas pogas. satur (poga); }
Jūs varētu sagaidīt metodi ar nosaukumu getButtons ()
iekšā PogaGrupa
klasē. Tas atgriež nemaināmu sarakstu, kurā ir atsauces uz grupas pogām. Nemainīgais saraksts novērš pogu pievienošanu vai noņemšanu, neizlaižot pogu grupas metodes. getElements ()
iekšā PogaGrupa
ne tikai nav pilnīgi iedvesmots vārds, bet arī atgriež Uzskaitīšana
, kas ir novecojusi klase, kuru nevajadzētu izmantot. Kolekciju ietvars nodrošina visu nepieciešamo, lai izvairītos no uzskaitīšanas. Tas ir kā getButtons ()
atgriež nemaināmu sarakstu:
public List getButtons () {return Collections.unmodifiableList (pogas); }
Uzlabot ButtonGroup
The JButtonGroup
klase piedāvā labāku un ērtāku alternatīvu Swing PogaGrupa
klasē, vienlaikus saglabājot visu superklases funkcionalitāti.
Uzziniet vairāk par šo tēmu
- Lejupielādējiet avota kodu, kas pievienots šim rakstam
//images.techhive.com/downloads/idge/imported/article/jvw/2003/09/jw-javatip142.zip
- Sun Microsystems Java Foundation Classes mājas lapa
//java.sun.com/products/jfc/
- Java 2 Platform, Standard Edition (J2SE) 1.4.2 API dokumentācija
//java.sun.com/j2se/1.4.2/docs/api/
- PogaGrupa klase
//java.sun.com/j2se/1.4.2/docs/api/javax/swing/ButtonGroup.html
- Skatīt visu iepriekšējo Java padomi un iesniedziet savu
//www.javaworld.com/columns/jw-tips-index.shtml
- Pārlūkot AWT / šūpoles sadaļa JavaWorld 's Aktuālais rādītājs
//www.javaworld.com/channel_content/jw-awt-index.shtml
- Pārlūkot Fonda nodarbības sadaļa JavaWorld 's Aktuālais rādītājs
//www.javaworld.com/channel_content/jw-foundation-index.shtml
- Pārlūkot Lietotāja saskarnes dizains sadaļa JavaWorld 's Aktuālais rādītājs
//www.javaworld.com/channel_content/jw-ui-index.shtml
- Apmeklējiet JavaWorld forumu
//www.javaworld.com/javaforums/ubbthreads.php?Cat=&C=2
- Pierakstieties JavaWorld 's bezmaksas iknedēļas e-pasta biļeteni
//www.javaworld.com/subscribe
Šo stāstu "Java Padoms 142: JButtonGroup virzīšana" sākotnēji publicēja JavaWorld.