Ohjelmointi

Swing-langoitus ja tapahtuma-lähetyslanka

Edellinen 1 2 3 4 5 Sivu 5 Sivu 5/5

Pidä Swing-lanka turvallisena

Viimeinen vaihe Swing-käyttöliittymän luomisessa on käynnistää se. Oikea tapa käynnistää Swing-käyttöliittymä tänään eroaa Sunin alun perin määräämästä lähestymistavasta. Tässä on jälleen lainaus Sunin dokumentaatiosta:

Kun Swing-komponentti on toteutettu, kaikki koodit, jotka saattavat vaikuttaa kyseisen komponentin tilaan tai riippua siitä, tulisi suorittaa tapahtumien lähettäjässä.

Heitä nuo ohjeet nyt ulos ikkunasta, sillä noin silloin, kun JSE 1.5 julkaistiin, kaikki Sunin esimerkit muuttuivat. Siitä lähtien se on ollut vähän tunnettu tosiasia, että sinun pitäisi aina pääsy Käännä tapahtuman lähetyslangan komponentteja varmistaaksesi niiden kierteen turvallisuus / yksisäikeinen pääsy. Muutoksen syy on yksinkertainen: vaikka ohjelmasi voisi käyttää Swing-komponenttia pois tapahtuma-lähetyskierteestä ennen komponentin toteutumista, Swing-käyttöliittymän alustaminen voi laukaista jotain suoritettavaksi tapahtuma-lähetyskierteessä jälkeenpäin, koska komponentti / käyttöliittymä odottaa suorittavan kaiken tapahtuman lähetysketjussa. GUI-komponenttien suorittaminen eri säikeillä rikkoo Swingin yksisäikeisen ohjelmointimallin.

Listing 5: n ohjelma ei ole aivan realistinen, mutta se auttaa tekemään mielipiteeni.

Listaus 5. Swing-komponenttitilan käyttö useista säikeistä

tuo java.awt. *; tuo java.awt.event. *; tuo javax.swing. *; public class BadSwingButton {public static void main (String args []) {JFrame-kehys = uusi JFrame ("Otsikko"); frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); JButton-painike = uusi JButton ("Paina tästä"); ContainerListener container = new ContainerAdapter () {public void componentAdded (final ContainerEvent e) {SwingWorker worker = new SwingWorker () {protected String doInBackground () throws InterruptedException {Thread.sleep (250); return null; } suojattu void done () {System.out.println ("Tapahtumaketjussa?:" + EventQueue.isDispatchThread ()); JButton-painike = (JButton) e.getChild (); Merkkijonotunniste = button.getText (); button.setText (tunniste + "0"); }}; työntekijä.toteuttaa (); }}; frame.getContentPane (). addContainerListener (säilö); frame.add (painike, BorderLayout.CENTER); frame.setSize (200, 200); kokeile {Thread.sleep (500); } catch (InterruptedException e) {} System.out.println ("Tulen ymmärtämään:" + EventQueue.isDispatchThread ()); frame.setVisible (true); }}

Huomaa, että lähtö näyttää jonkin koodin käynnissä pääkierteessä ennen käyttöliittymän toteuttamista. Tämä tarkoittaa, että alustuskoodi on käynnissä yhdellä säikeellä, kun taas toinen käyttöliittymäkoodi on käynnissä tapahtuma-lähetyskierroksessa, mikä rikkoo Swingin yksisäikeisen pääsymallin:

> java BadSwingButton Tapahtumaketjussa? : totta Olen ymmärtämässä: väärä

Listauksen 5 ohjelma päivittää painikkeen tunnisteen säilön kuuntelijasta, kun painike lisätään säilöön. Jos haluat tehdä skenaariosta realistisemman, kuvittele käyttöliittymä, joka "laskee" siihen tarrat ja käyttää lukua reunanimikkeen tekstinä. Luonnollisesti sen on päivitettävä reunuksen otsikkoteksti tapahtuma-lähetyssäikeessä. Jotta asiat olisivat yksinkertaisia, ohjelma päivittää vain yhden painikkeen etiketin. Vaikka toiminto ei ole realistinen, se näyttää ongelman joka Swing-ohjelma, joka on kirjoitettu Swing-ajan alusta lähtien. (Tai ainakin kaikki ne, jotka noudattivat suositeltua langoitusmallia, joka löytyy javadocsista ja Sun Microsystemsin online-opetusohjelmista ja jopa omista Swing-ohjelmakirjojeni varhaisista painoksista.)

Langan langoitus on tehty oikein

Tapa saada Swing-langoitus oikein on unohtaa Sunin alkuperäinen sanelu. Älä huoli siitä, onko komponentti toteutunut vai ei. Älä vaivaudu yrittämään selvittää, onko jotain turvallista käyttää tapahtuman lähetyslangasta. Se ei ole koskaan. Luo sen sijaan koko käyttöliittymä tapahtuman lähetyslangalle. Jos sijoitat koko käyttöliittymän luomiskutsun EventQueue.invokeLater () kaikki käyttöoikeudet alustuksen aikana taataan tapahtuman lähetysketjussa. Se on niin yksinkertaista.

Listaus 6. Kaikki paikoillaan

tuo java.awt. *; tuo java.awt.event. *; tuo javax.swing. *; public class GoodSwingButton {public static void main (String args []) {Runnable runner = new Runnable () {public void run () {JFrame frame = new JFrame ("Title"); frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); JButton-painike = uusi JButton ("Paina tästä"); ContainerListener container = new ContainerAdapter () {public void componentAdded (final ContainerEvent e) {SwingWorker worker = new SwingWorker () {suojattu String doInBackground () heittää InterruptedException {return null; } suojattu void done () {System.out.println ("Tapahtumaketjussa?:" + EventQueue.isDispatchThread ()); JButton-painike = (JButton) e.getChild (); Merkkijonotunniste = button.getText (); button.setText (tunniste + "0"); }}; työntekijä.toteuttaa (); }}; frame.getContentPane (). addContainerListener (säilö); frame.add (painike, BorderLayout.CENTER); frame.setSize (200, 200); System.out.println ("Olen ymmärtämässä:" + EventQueue.isDispatchThread ()); frame.setVisible (true); }}; EventQueue.invokeLater (juoksija); }}

Suorita se nyt ja yllä oleva ohjelma osoittaa, että sekä alustus- että säilökoodi ovat käynnissä tapahtuma-lähetyskierteessä:

> java GoodSwingButton Tulen ymmärtämään: totta Tapahtumaketjussa? : totta

Tiivistettynä

Ylimääräinen käyttöliittymän luominen tapahtuma-lähetyslangassa saattaa tuntua aluksi tarpeettomalta. Kaikki ovat tehneet sitä toisinpäin aikojen alusta lähtien. Miksi vaivautua muuttumaan nyt? Asia on, että olemme aina tehneet sen väärin. Varmistaaksesi, että Swing-komponenttejasi käytetään oikein, sinun on aina luotava koko käyttöliittymä tapahtuma-lähetyskierteessä, kuten tässä on esitetty:

Runnable runner = uusi Runnable () {public void run () {// ... luo käyttöliittymä tähän ...}} EventQueue.invokeLater (runner);

Alustuskoodin siirtäminen tapahtuma-lähetyslangalle on ainoa tapa varmistaa, että Swing-käyttöliittymät ovat langattomia. Kyllä, se tuntuu aluksi hankalalta, mutta edistyminen yleensä tapahtuu.

John Zukowski on pelannut Javalla jo yli 12 vuotta, luopunut C- ja X-Windows-ajattelutapastaan ​​kauan sitten. Johnilla on 10 kirjaa aiheesta Swingistä kokoelmiin Java SE 6: een, ja nyt hän tarjoaa strategista konsultointia liiketoimintansa JZ Ventures, Inc.:n kautta.

Lisätietoja tästä aiheesta

  • Lisätietoja Swing-ohjelmoinnista ja tapahtuman lähetyslangasta yhdeltä Java-työpöydän kehityksen päälliköltä: Chet Haase Swingin ja Java 2D: n maksimoinnista (JavaWorld Java Technology Insider podcast, elokuu 2007).
  • "SwingWorkerin mukauttaminen parantamaan Swing-käyttöliittymiä" (Yexin Chen, JavaWorld, kesäkuu 2003) kaivaa syvemmälle joitain tässä artikkelissa käsitellyistä Swing-langoituksen haasteista ja selittää, kuinka mukautettu SwingWorker voi tarjota lihaksen kiertää heidän ympärillään.
  • "Java ja tapahtumankäsittely" (Todd Sundsted, JavaWorld, elokuu 1996) on alusta tapahtumien käsittelystä noin AWT: ssä.
  • "Nopeuta kuuntelijan ilmoitusta" (Robert Hastings, JavaWorld, helmikuu 2000) esittelee JavaBeans 1.0 -määrityksen tapahtumien rekisteröintiä ja ilmoituksia varten.
  • "Saavuta vahva suorituskyky säikeillä, osa 1" (Jeff Friesen, JavaWorld, toukokuu 2002) esittelee Java-ketjut. Katso osa 2 vastauksesta kysymykseen: Miksi tarvitsemme synkronointia?
  • "Tehtävien suorittaminen ketjuina" on JavaWorld-ote Java-samanaikaisuus käytännössä (Brian Goetz et ai., Addison Wesley Professional, toukokuu 2006), joka kannustaa tehtävälähtöiseen ketjun ohjelmointiin ja esittelee suorituksen kehyksen tehtävien hallintaan.
  • "Langat ja keinut" (Hans Muller ja Kathy Walrath, huhtikuu 1998) on yksi varhaisimmista virallisista viitteistä Swing-langoitukseen. Se sisältää nyt kuuluisan (ja virheellisen) "yksisäikeisen säännön".
  • GUI: n luominen JFC / Swingillä on kattava Java-opetusohjelma Swing GUI -ohjelmointia varten.
  • "Samanaikaisuus Swingissä" on Swing-reitin opetusohjelma, joka sisältää johdannon SwingWorker luokassa.
  • JSR 296: Swing-sovelluskehys on tällä hetkellä erittelyssä. Katso myös "Swing-sovelluskehyksen käyttö" (John O'Conner, Sun Developer Network, heinäkuu 2007) saadaksesi lisätietoja Swing-käyttöliittymän ohjelmoinnin seuraavasta vaiheesta.
  • Koko Java AWT Reference (John Zukowski, O'Reilly, maaliskuu 1997) on saatavana ilmaiseksi O'Reilly Online -luettelosta.
  • John's Definitive Guide to Java Swing, kolmas painos (Apress, kesäkuu 2005) on täysin päivitetty Java Standard Edition -versioon 5.0. Lue kirjan esikatseluluku täältä JavaWorld!
  • Käy JavaWorld Swing / GUI -tutkimuskeskuksessa saadaksesi lisää artikkeleita Swing-ohjelmoinnista ja Java-työpöydän kehityksestä.
  • Tutustu myös JavaWorld-kehittäjäfoorumeihin keskusteluihin ja kysymyksiin ja vastauksiin liittyen Swingiin ja Java-työpöytäohjelmointiin.

Tämän tarinan "Swing threading and the event-dispatch thread" julkaisi alun perin JavaWorld.