Swing navoja i nit za slanje događaja

Prethodna 1 2 3 4 5 Stranica 5 Stranica 5 od 5

Održavanje navoja Swing na sigurnom

Posljednji korak u stvaranju Swing GUI-a je njegovo pokretanje. Ispravan način pokretanja Swing GUI-a danas se razlikuje od Sunčevog izvorno propisanog pristupa. Evo opet citata iz dokumentacije Sunca:

Jednom kada se Swing komponenta realizira, sav kôd koji može utjecati ili ovisi o stanju te komponente trebao bi se izvršiti u niti otpreme događaja.

Bacite te upute kroz prozor, jer su se oko izdavanja JSE 1.5 svi primjeri na Sunčevoj stranici promijenili. Od tada je malo poznata činjenica da biste trebali uvijek pristupati Swing komponentama na niti otpreme događaja kako biste osigurali sigurnost niti / pristup s jednim navojem. Razlog promjene je jednostavan: iako bi vaš program mogao pristupiti Swing komponenti s niti događaja-otpreme prije nego što je komponenta realizirana, inicijalizacija Swing UI-a mogla bi pokrenuti nešto da se pokrene na niti događaja-otpreme nakon toga, jer komponenta / korisničko sučelje očekuje pokretanje svega na niti otpreme događaja. Pokretanje GUI komponenata na različitim nitima ruši Swingov jednonitni programski model.

Program s popisa 5 nije sasvim realan, ali služi za postizanje mojeg stava.

Popis 5. Pristup stanju Swing komponente iz više niti

import java.awt.*; import java.awt.event.*; import javax.swing.*; public class BadSwingButton { public static void main(String args[]) { JFrame frame = new JFrame("Title"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JButton button = new JButton("Press Here"); ContainerListener container = new ContainerAdapter() { public void componentAdded(final ContainerEvent e) { SwingWorker worker = new SwingWorker() { protected String doInBackground() throws InterruptedException { Thread.sleep(250); return null; } protected void done() { System.out.println("On the event thread? : " + EventQueue.isDispatchThread()); JButton button = (JButton)e.getChild(); String label = button.getText(); button.setText(label + "0"); } }; worker.execute(); } }; frame.getContentPane().addContainerListener(container); frame.add(button, BorderLayout.CENTER); frame.setSize(200, 200); try { Thread.sleep(500); } catch (InterruptedException e) { } System.out.println("I'm about to be realized: " + EventQueue.isDispatchThread()); frame.setVisible(true); } }

Primijetite da izlaz prikazuje neki kôd pokrenut na glavnoj niti prije realizacije korisničkog sučelja. To znači da se inicijalizacijski kôd izvodi na jednoj niti, dok se drugi UI kôd izvodi na niti otpreme događaja, što prekida Swingov model s jednim navojem:

> java BadSwingButton On the event thread? : true I'm about to be realized: false

Program iz popisa 5 ažurirat će oznaku gumba iz preslušača spremnika kad se gumb doda u spremnik. Da biste scenarij učinili realnijim, zamislite korisničko sučelje koje u njemu "broji" oznake i koristi brojanje kao tekst u naslovu obruba. Naravno, trebalo bi ažurirati tekst naslova obruba u niti otpreme događaja. Da bi stvari bile jednostavne, program samo ažurira oznaku jednog gumba. Iako nije realan u funkciji, ovaj program prikazuje problem sa svakim Swing programom koji je napisan od početka Swingova vremena. (Ili barem svi oni koji su slijedili preporučeni model navoja navoja koji se nalazi u javadocsima i mrežnim vodičima Sun Microsystems, pa čak i u mojim vlastitim ranim izdanjima Swing knjiga o programiranju.)

Zamah navojem izveden kako treba

Način da Swing navojem napravite ispravno je da zaboravite Sunčev izvorni izraz. Ne brinite hoće li se komponenta realizirati ili ne. Ne zamarajte se pokušavajući utvrditi je li sigurno pristupiti nečemu izvan niti za slanje događaja. Nikad nije. Umjesto toga, stvorite cijelo korisničko sučelje na niti otpreme događaja. Ako smjestite cijeli poziv za stvaranje korisničkog sučelja unutar EventQueue.invokeLater()svih pristupa tijekom inicijalizacije, zajamčeno je da će se obaviti u niti otpreme događaja. To je tako jednostavno.

Popis 6. Sve na svom mjestu

import java.awt.*; import java.awt.event.*; import 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 button = new JButton("Press Here"); ContainerListener container = new ContainerAdapter() { public void componentAdded(final ContainerEvent e) { SwingWorker worker = new SwingWorker() { protected String doInBackground() throws InterruptedException { return null; } protected void done() { System.out.println("On the event thread? : " + EventQueue.isDispatchThread()); JButton button = (JButton)e.getChild(); String label = button.getText(); button.setText(label + "0"); } }; worker.execute(); } }; frame.getContentPane().addContainerListener(container); frame.add(button, BorderLayout.CENTER); frame.setSize(200, 200); System.out.println("I'm about to be realized: " + EventQueue.isDispatchThread()); frame.setVisible(true); } }; EventQueue.invokeLater(runner); } }

Pokrenite ga sada i gornji program će pokazati da se i inicijalizacija i kod spremnika izvode na niti otpreme događaja:

> java GoodSwingButton I'm about to be realized: true On the event thread? : true

U zaključku

Dodatni posao na stvaranju vašeg korisničkog sučelja u niti otpreme događaja mogao bi se u početku činiti nepotrebnim. Napokon, svi to rade na drugi način. Zašto se sada truditi mijenjati? Stvar je u tome što smo to uvijek radili pogrešno. Da biste osigurali ispravni pristup svojim Swing komponentama, uvijek biste trebali stvoriti cijelo korisničko sučelje u niti otpreme događaja, kao što je prikazano ovdje:

Runnable runner = new Runnable() { public void run() { // ...create UI here... } } EventQueue.invokeLater(runner);

Premještanje vašeg inicijalizacijskog koda u nit za otpremu događaja jedini je način da osigurate da su vaši Swing GUI zaštićeni od niti. Da, u početku će se osjećati neugodno, ali napredak obično jest.

John Zukowski već se više od 12 godina igra s Javom, davno je napustivši svoj C i X-Windows način razmišljanja. S 10 knjiga na teme od Swinga do zbirki do Jave SE 6, John sada obavlja strateško tehnološko savjetovanje kroz svoje poslovanje, JZ Ventures, Inc ..

Saznajte više o ovoj temi

  • Saznajte više o Swing programiranju i niti za slanje događaja od jednog od glavnih programera razvoja Java radne površine: Chet Haase o maksimiziranju Swinga i Jave 2D (podcast JavaWorld Java Technology Insider, kolovoz 2007.).
  • "Prilagodite SwingWorker za poboljšanje Swing GUI-ja" (Yexin Chen, JavaWorld, lipanj 2003.) dublje istražuje neke od izazova Swing navoja koji su razmotreni u ovom članku i objašnjava kako prilagođeni SwingWorkermogu pružiti mišiću da zaobiđe njih.
  • "Java i rukovanje događajima" (Todd Sundsted, JavaWorld, kolovoz 1996.) temeljni je tekst o rukovanju događajima oko AWT-a.
  • "Ubrzavanje obavijesti slušatelja" (Robert Hastings, JavaWorld, veljača 2000.) uvodi JavaBeans 1.0 specifikaciju za registraciju događaja i obavijesti.
  • "Postignite snažne performanse pomoću niti, 1. dio" (Jeff Friesen, JavaWorld, svibanj 2002.) uvodi Java niti. Odgovor na pitanje: Zašto nam je potrebna sinkronizacija potražite u 2. dijelu.
  • "Izvršavanje zadataka u nitima" izvadak je JavaWorlda iz Java Concurrency in Practice (Brian Goetz i dr., Addison Wesley Professional, svibanj 2006.) koji potiče programiranje niti temeljeno na zadacima i uvodi izvršni okvir za upravljanje zadacima.
  • "Niti i zamah" (Hans Muller i Kathy Walrath, travanj 1998.) jedna je od najranijih službenih referenci za navoj Swinga. Uključuje sada poznato (i pogrešno) "pravilo s jednom niti".
  • Stvaranje GUI-a s JFC / Swing sveobuhvatna je stranica s Java tutorijalom za Swing GUI programiranje.
  • "Concurrency in Swing" je vodič na Swing stazi koji uključuje uvod u SwingWorkernastavu.
  • JSR 296: Swing Application Framework trenutno je specifikacija u tijeku. Također pogledajte "Korištenje Swing Application Framework-a" (John O'Conner, Sun Developer Network, srpanj 2007.) da biste saznali više o ovom sljedećem koraku u evoluciji Swing GUI programiranja.
  • Cjelokupna Java AWT referenca (John Zukowski, O'Reilly, ožujak 1997.) dostupna je besplatno iz internetskog kataloga O'Reilly.
  • John-ov Definitivan vodič za Java Swing, treće izdanje (Apress, lipanj 2005.) potpuno je ažuriran za Java Standard Edition verzije 5.0. Pročitajte poglavlje pregleda iz knjige upravo ovdje na JavaWorldu !
  • Posjetite JavaWorld Swing / GUI istraživački centar za više članaka o Swing programiranju i razvoju Java radne površine.
  • Također potražite forume za programere JavaWorld za rasprave i pitanja u vezi s Swingom i Java programiranjem na radnoj površini.

Ovu priču, "Swing navoja i nit za slanje događaja" izvorno je objavio JavaWorld.