Procesul de dezvoltare a unui program GUI simplu în Java. Crearea unei GUI în Java Java awt exemple

Davydov Anton Valerievici
Student la TSU, Rusia, Tolyatti
Consilier stiintific: Erofeeva E.A.

Interfața cu utilizatorul din Java a trecut printr-o cale foarte spinoasă de formare și dezvoltare. A fost mult timp acuzat de lăcomie față de resursele sistemului, performanță lentă și funcționalitate limitată. Apariția .NET cu componente grafice mai rapide a subminat și mai mult poziția Java. Dar o astfel de competiție a determinat doar dezvoltatorii Java să dezvolte și să îmbunătățească bibliotecile grafice. Și în acest articol vom vedea ce a rezultat.

Setul de instrumente pentru fereastra abstractă

Abstract Window Toolkit (AWT pe scurt) a fost lansat pentru prima dată în 1995 de Sun Microsystems. Aceasta a fost prima încercare de a crea un GUI pentru Java. AWT a acționat ca un strat care a numit metode din bibliotecile scrise în C. Și aceste metode, la rândul lor, au folosit componentele grafice ale sistemului de operare. Pe de o parte, un program construit în acest fel era similar extern cu toate celelalte programe din sistemul de operare utilizat, dar, pe de altă parte, același program poate arăta complet diferit pe sisteme de operare diferite, ceea ce a complicat dezvoltarea. În plus, de dragul multiplatformei, a fost necesară unificarea interfețelor de apelare a componentelor, ceea ce a dus la funcționalitatea oarecum redusă. Setul de componente este, de asemenea, destul de modest. De exemplu, nu există tabele, iar pictogramele nu pot fi plasate în butoane. AWT încearcă să elibereze automat resursele utilizate. Acest lucru afectează performanța și adaugă complexitate arhitecturii. AWT este ușor de învățat, dar a scrie ceva complex este o provocare. În zilele noastre AWT este folosit în principal pentru applet-uri. Oracle încurajează în prezent dezvoltatorii să treacă la Swing, deoarece este mai sigur.

Fig. 1 – Exemplu de program scris folosind AWT în mediul Windows

După AWT, Sun a lansat Swing în 1998. Este scris în întregime în Java și folosește 2D pentru randare. Swing are componente mult mai diferite decât AWT. Componentele în sine au devenit mult mai ușor de creat prin moștenirea lor de la cele existente. A fost introdusă și capacitatea de a folosi diferite stiluri și skinuri. Cu toate acestea, viteza versiunilor timpurii de Swing a fost destul de scăzută, iar erorile în scrierea programelor ar putea duce chiar la înghețarea sistemului de operare.

Cu toate acestea, datorită ușurinței sale de învățare și a documentării extinse, Swing a devenit cea mai populară GUI din Java. A dat naștere multor extensii, cum ar fi SwingX și JGoodies, care fac și mai ușoară crearea de aplicații complexe vizual. Toate mediile moderne de programare Java includ editori grafici Swing. Chiar dacă acum există cadre mai moderne, Swing rămâne cel mai popular.


Fig.2 – Exemplu de program scris folosind Swing

Setul de instrumente Widget standard

SWT a fost lansat de IBM într-un moment în care Swing era încă lent și, în principal, pentru a promova mediul de programare Eclipse. La fel ca AWT, SWT utilizează componente ale sistemului de operare, dar diferite interfețe de interoperabilitate sunt folosite pentru diferite platforme. Astfel, pentru fiecare sistem de operare trebuie furnizată o bibliotecă JAR separată. Acest lucru vă permite să utilizați mai pe deplin funcțiile care se potrivesc diferitelor sisteme de operare. Iar componentele lipsă au fost realizate folosind 2D. Cu toate acestea, SWT s-a dovedit a fi mai dificil de stăpânit decât Swing. În plus, programatorul trebuie să implementeze el însuși eliberarea de resurse de către aplicație.

Fig.3 – Exemplu de program scris folosind Swing

JavaFX a fost lansat în 2008 de Oracle. Este poziționat ca o platformă pentru crearea de aplicații Internet bogate. Conducta grafică este folosită pentru randare, ceea ce accelerează semnificativ aplicația. Există un set mare de componente încorporate. Există, de asemenea, componente separate pentru trasare. Este implementat suport pentru conținut multimedia, animație și chiar mai multe atingeri. Aspectul componentelor este personalizat folosind stiluri CSS. În plus, setul de utilități JavaFX include posibilitatea de a crea un program de instalare nativ pentru cele mai populare platforme: exe sau msi pentru Windows, deb sau rpm pentru Linux, dmg pentru Mac. Site-ul web Oracle are documentație detaliată și un număr mare de exemple gata făcute.

Astfel, după ce am descris principalele caracteristici și dezavantaje ale interfețelor grafice de mai sus, putem decide pentru ce sarcini sunt mai potrivite. Abstract Window Toolkit este mai potrivit pentru crearea de applet-uri. Pentru un începător, putem recomanda Swing datorită faptului că puteți găsi o cantitate imensă de documentație pentru acesta pe Internet, inclusiv în limba rusă. JavaFX este perfect pentru a crea aplicații bogate pentru Internet.

Lista surselor utilizate

    Ryzhenko A. V. Programare orientată pe obiecte: Complex educațional și metodologic în disciplina pentru specialitatea 010501 - „Matematică aplicată și informatică”. – 2007.

    Khabibullin I. Sh. Java 7 (ed. a IV-a). – BHV-Petersburg, 2012.

    Clarke J., Connors J., Bruno E. J. JavaFX: Dezvoltarea de aplicații Internet bogate. – Pearson Education, 2009.

    Northover S., Wilson M. Swt: trusa de instrumente widget standard, volumul 1. – Addison Wesley Professional, 2004.

Descrierea prezentării Crearea unei interfețe grafice în biblioteci Java Graphic pentru diapozitive

Biblioteci de grafică Java Java are următoarele pachete pentru crearea interfețelor grafice: Abstract Windows Toolkit (AWT) - vine cu JDK, fiecare componentă AWT are propria sa componentă vizuală (peer) pentru un anumit OS, portabilitatea este asigurată de pachetul java. awt. egal; set limitat de componente grafice; Aspectul depinde de sistemul de operare. Standard Widget Toolkit (SWT) - furnizat separat pentru anumite sisteme de operare, incluse în mediul Eclipce, interacționează cu sistemul de operare folosind interfețe peer, spre deosebire de AWT, gama de componente a fost extinsă. Swing – vine cu JDK, extinde clasele AWT, nu depinde de componentele peer OS. Java 3 D – grafică tridimensională.

Componente grele și ușoare Componente grele – Redate de sistemul de operare – Majoritatea componentelor AWT Componente ușoare – Redate prin cod java – Toate componentele Swing, cu excepția ferestrelor de nivel superior (fereastra aplicației) Componentele grele sunt întotdeauna desenate deasupra celor ușoare

Arhitectura Model-View-Controller (MVC) Modelul de proiectare MVC implică separarea datelor aplicației, a interfeței cu utilizatorul și a logicii de control în trei componente separate – model, vizualizare și controler – astfel încât fiecare componentă să poată fi modificată independent. Modelul stochează datele componentei și facilitează schimbarea sau preluarea acestor date fără a accesa componenta în sine. O vizualizare afișează date pe ecran pentru a le prezenta utilizatorului. Controlerul definește modul în care vizualizarea și datele modelului ar trebui să reacționeze ca răspuns la intrarea utilizatorului.

Avantajele MVC Puteți atașa mai multe vederi unui singur model fără a afecta implementarea modelului. De exemplu, unele date pot fi prezentate simultan ca o foaie de calcul, o histogramă și o diagramă circulară. Fără a afecta implementarea vizualizărilor, puteți modifica reacțiile la acțiunile utilizatorului (făcând clic pe un buton, introducerea datelor); pentru a face acest lucru, trebuie doar să utilizați un controler diferit. O serie de dezvoltatori se specializează doar în unul dintre domenii: fie dezvoltarea unei interfețe grafice, fie dezvoltarea logicii de afaceri. Prin urmare, este posibil să ne asigurăm că programatorii care dezvoltă logica de afaceri (modelul) nu vor fi deloc conștienți de ce reprezentare va fi utilizată.

Interacțiuni între model, vizualizare și controler Model clasic Legătură strânsă între controler și model și controler și vizualizare. O vizualizare este asociată cu un singur controler și fiecare controler cu o singură vizualizare. Vizualizarea și controlerul au o legătură directă către model.

Exemplu MVC Public class Model ( private int int. Array = (1, 2, 3, 4, 5); public String get. String. Array() ( return "int. Array=" + Arrays. to. String(int. Array); ) public void set. Int. Array(int index, int value) ( ​​​​this. int. Array = valoare; ) ) public class Controller ( Model model = new Model(); View view = new View() ; Controller ()( update. View(); ) void set. Array. Value(int index, int value) (​model. set. Int. Array(index, value); update. View(); ) void update . View() ( vizualizare. arată. Array(model. get. String. Array()); ) ) public class View ( public void show. Array(String array. String)( System. out. println("View") ; System. out . println(array. String); System. out. println(); ) ) public class User ( public statc void main(String args) ( Controller controller = new Controller(); controller. set. Array. Value (1, 4); ))

Modelul Swing simplifică implementarea.Modelul nu știe cu ce proxy UI colaborează și ce componentă îl folosește.Setează aspectul și comportamentul pentru toate componentele bibliotecii.Este asociat cu modelul numai prin clasa de componente. Controlerul de vizualizare procesează evenimentele utilizatorului și desenează componente pe ecran Butoane, liste, tabele, câmpuri de text...

Componentele interfeței Buton - buton; JVerificați. Casetă—buton casetă de selectare; JCombo. Casetă - listă derulantă; JLabel - etichetă, inscripție; JList - listă; JParolă. Câmp — câmp de text pentru introducere ascunsă; JProgress. Bară - o componentă pentru afișarea unui număr într-un anumit interval; JRadio. Button - butoane radio, utilizate de obicei cu componenta Button. Grup; JSlider - o componentă care vă permite să selectați o valoare dintr-un interval dat; JTable - masă; JText. Câmp - câmp text cu un rând; JText. Zona - câmp text cu mai multe linii; JTree - copac.

Containere de interfață Părți ale interfeței utilizator care conțin alte componente Containere de nivel superior: Frame, JFrame - fereastra aplicației; JDialog - dialog aplicație; JColor. Selector - dialog de selectare a culorii; JFile. Chooser - dialog pentru selectarea fișierelor și directoarelor; Fişier. Dialog - dialog pentru selectarea fișierelor și directoarelor (componenta awt). Containere simple: JPanel - un panou simplu pentru gruparea elementelor, inclusiv panouri imbricate; JTool. Bară - bară de instrumente (de obicei butoane); JScroll. Panou - un panou de defilare care vă permite să defilați conținutul unui element copil; JDesktop. Panoul este un container pentru crearea unui desktop virtual sau aplicații bazate pe MDI (interfață cu mai multe documente); JEditor. Panoul, JText. Panoul - containere pentru afișarea unui document complex ca HTML sau RTF; JTabbed. Panoul - container pentru gestionarea marcajelor;

Crearea ferestrei de import java. awt. *; clasa de asemenea. Simplu. Frame extinde Frame( public statc void main(String args)( Frame fr = new Too. Simplu. Frame(); fr. set. Size (400, 150); // dimensiunea ferestrei fr. set. Vizibil (adevărat); / / redarea ferestrei ) // butonul de închidere nu funcționează ) Swing

Fereastră cu o pictogramă personalizată import javax. leagăn. *; Cadru de clasă publică. Închiderea extinde JFrame ( public Frame. Closing() ( super("Window Title"); // operațiune la închiderea setului de ferestre. Implicit. Închidere. Operaton(EXIT_ON_CLOSE); // la închiderea ferestrei - ieșire // pictograma pentru set de ferestre. Pictogramă. Imagine(get. Toolkit(). get. Image("pictogramă. gif")); //C: / pictograme / pictogramă. png // set de afișare. Dimensiune (300, 100); // fereastră mărimi setate lățimea și înălțimea. Vizibil (adevărat); // vizualizare fereastră ) public statc void main(String args) ( cadru nou. Închidere (); ) ) Swing

Casete de dialog standard Tip casetă de dialog Descriere NFORMATION_MESSAGE Caseta de dialog afișează informații generale cu o pictogramă ca aceasta. caseta de dialog nu este unul dintre tipurile de mai sus. Afișat pe ecran fără pictogramă standard. Casetele de dialog pot fi modale sau fără model Casetele de dialog pot fi modale (concentrați-vă pe fereastră până când se apasă butonul) sau fără model

Ferestrele de intrare și mesaje import java. awt. *; import javax. leagăn. *; clasă publică Soluton ( public static void main(String args) ( JOpton. Panoul. Afișați. Mesaj. Dialog(null , „Bună ziua, Lume”); String s = JOpton. Panoul. Afișați. Intrare. Dialog(„Introduceți numele dvs.” ); ) ) Leagăn

Legături standard Java 1. Legătură de frontieră. Aspect (plasare polară). 2. Flow Composer. Aspect (plasare secvenţială). 3. Linker. Grilă. Aspect (dispunerea tabelului). 4. Element de legătură cu arc. Aspect (plasare relativă). 5. Box Composer. Aspect (plasarea blocului).

Polar Layout (Border. Layout Composer) Valoare chenar. Aspect. NORD sau șirul „Nord” - componenta este situată de-a lungul marginii superioare (nordice) a ferestrei și se întinde pe întreaga sa lățime. Acesta este, de obicei, modul în care este plasată bara de instrumente. Sensul de frontieră. Aspect. SUD sau șirul „Sud” - componenta este situată de-a lungul marginii de jos (sud) și se întinde pe toată lățimea ferestrei. Această poziție este ideală pentru bara de stare. Sensul de frontieră. Aspect. VEST sau șirul „Vest” - componenta este situată de-a lungul marginii din stânga (vest) a ferestrei și se întinde pe întreaga sa înălțime, cu toate acestea, se iau în considerare dimensiunile componentelor nordice și sudice (au prioritate). Sensul de frontieră. Aspect. EST sau șirul „Est” - componenta este situată de-a lungul marginii din dreapta (estică) a ferestrei. În rest, aspectul său este similar cu componenta vestică. Sensul de frontieră. Aspect. CENTER sau șirul „Center” - componenta este plasată în centrul ferestrei, ocupând cât mai mult spațiu posibil.

Un exemplu de utilizare a compozitorului Border. Layout import javax. leagăn. *; import java. awt. *; Frontieră de clasă publică. Aspect. Sample extinde JFrame ( public Border. Layout. Sample() ( super("Border. Layout. Sample"); set. Size(400, 300); set. Implicit. Close. Operaton(EXIT_ON_CLOSE); // obțineți conținutul clasei panel JFrame Container c = get. Content. Pane(); // Implicit, Swing folosește Border. Layout Manager // adaugă componente la panou folosind constante șir c. add(new JButton("North"), "North" ); c. add(new JButton("South"), "South"); // sau constante din Border. Clasa de aspect // Element JLabel pentru afișarea textului c. add(new JLabel("West"), Border. Layout. WEST) ; c. add(new JLabel("East"), Border. Layout. EAST); // dacă parametrul nu este specificat deloc, componenta va fi adăugată automat în centru c. add(new JButton ("Centru")); // afișează setul de fereastră la ecran. Vizibil (adevărat); ) public statc void main (Argumente șir) ( chenar nou. Aspect. Exemplu (); ) ) Swing

Aspect secvenţial (Aspect flux) Aspectul prezintă componente de la stânga la dreapta, de sus în jos (implicit în Jpanels). import javax. leagăn. *; import java. awt. *; Flow de clasă publică. Aspect. Sample extinde JFrame ( public Flow. Layout. Sample() ( super("Flow. Layout 1"); set. Size(400, 200); set. Implicit. Close. Operaton(EXIT_ON_CLOSE); // obțineți panoul de conținut Container c = obține. Conținut. Panou(); // setează o aranjare secvențială cu componentele aliniate la centru c. set. Layout(new Flow. Layout(Flow. Layout. CENTER)); // adaugă componente c. add( JButton nou ("Unul")); c. add (JButton nou ("Doi")); c. add(JButton nou ("Trei")); // afișează setul de ferestre. Vizibil (adevărat); ) stat public void main( String args) (nou Flow. Layout. Sample(); ) ) import java. awt. *; import javax. leagăn. *; clasă publică Soluton ( public static void main(String args) ( JOpton. Panoul. Afișare. Mesaj. Dialog(null , „Bună ziua, lume”); ) ) Swing

Aspect tabelar (Dispozitiv Grid. Aspect) toate componentele au aceeași dimensiune. Spațiul disponibil este împărțit într-un număr egal de celule, fiecare dintre acestea conținând o componentă; toate componentele sunt întotdeauna afișate pe ecran, indiferent cât de mare sau mic este spațiul disponibil. import java. awt. *; import javax. leagăn. *; import java. utl. *; classGrid. Testul extinde JFrame ( Grid. Test(String s)( super(s); Container c = get. Content. Pane(); // 4 rânduri 4 coloane distanță între rânduri și coloane în pixeli c. set. Layout (nouă Grid. Layout(4, 4, 5, 5)); String. Tokenizer st = new String. Tokenizer("7 8 9 / 4 5 6 * 1 2 3 - 0. = +"); while(st. are. Mai mult. Tokens()) c. add(new Button(st. next. Token())); set. Size(200, 200); set. Visible(true); ) public statc void main(String args)( new Grid. Test ("Grid. Layout Manager"); ) ) Swing

O aranjare tabulară va oferi butoanelor aceeași dimensiune, iar o aranjare secvențială le va împiedica să „se încețească” și, în același timp, le va alinia la marginea dreaptă I mport java. awt. *; import javax. leagăn. *; Comandamentul clasei publice. Butoanele extinde JFrame ( Comandă publică. Butoane() ( super(„Comandă. Butoane”); set. Size(350, 250); set. Locaton(150, 100); set. Implicit. Închidere. Operaton(EXIT_ON_CLOSE); / / creați un panou cu un aspect de tabel pentru a alinia dimensiunile butoanelor JPanel grid = new JPanel(new Grid. Layout(1, 2, 5, 0)); // 1 rând, 2 coloane, 5 px orizontal, 0 vertical . // adăugați grilă de componente. add(new JButton("OK")); grid. add(new JButton("Anulați")); // plasați cel rezultat în panou cu o aranjare secvențială, aliniat la dreapta JPanel flux = nou JPanel(nou Flow. Layout(Flow. Layout. DREAPTA)); flow. add(grid); // obține panoul de conținut Container c = get. Content. Pane(); // plasează un rând de butoane la partea de jos a ferestrei c. add(flow, Border . Layout. SOUTH); // afișează setul de ferestre. Visible(true); ) public statc void main(String args) (comandă nouă. Butoane(); ) ) Swing

Aspect bloc (Box. Compozitor layout) Managerul de layout bloc dispune componente într-un container în blocuri: o coloană (de-a lungul axei Y) sau o bandă (de-a lungul axei X), iar fiecare componentă individuală poate fi aliniată centrat, stânga sau dreapta, precum și în partea de sus sau de jos.

Exemplu de aspect bloc import java. awt. *; import javax. leagăn. *; Public class Box 1 extinde JFrame ( public Box 1() ( super("Box 1 - Y"); set. Size(400, 200); set. Implicit. Close. Operaton(EXIT_ON_CLOSE); // obține panoul de conținut Container c = obține. Conținut. Panou(); // setează aspectul blocului de-a lungul axei Y (coloana) Caseta. Aspect boxy = casetă nouă. Layout (c, Box. Layout. Y_AXIS); c. set. Layout (boxy) ; // adaugă componente c. add(new JButton("One")); c. add(new JButton("Doi")); c. add(new JButton("Trei")); // afișează setul de ferestre . Vizibil (adevărat); ) clasă statc Box 2 extinde JFrame ( public Box 2() ( super("Box 2 - X"); // setează dimensiunea și poziția setului de ferestre. Size(400, 200); set . Locaton(100, 100); set. Implicit. Închidere. Operaton(EXIT_ON_CLOSE); // obțineți panoul de conținut Container c = obține. Conținut. Panou(); // setați aspectul blocului de-a lungul casetei axei X (dungi) . Layout boxx = new Box. Layout (c, Box. Layout. X_AXIS); c. set. Layout(boxx); // adăugați componente c. add(new JButton ("One")); c. add(new JButton ("Doi")); c . add(new JButton ("Trei")); // afișează setul de ferestre. Vizibil (adevărat); ) ) public statc void main(String args) ( new Box 1(); new Box 2(); ) ) Swing 5 Acest exemplu creează două ferestre. Unul dintre ele implementează un aspect de bloc de-a lungul axei Y, celălalt implementează un aspect de bloc de-a lungul axei X.

Interfața cu utilizatorul din Java a trecut printr-o cale foarte spinoasă de formare și dezvoltare. Multă vreme a fost acuzat de muncă lentă, lăcomie pentru resursele sistemului și funcționalitate limitată. Apariția .NET cu componente grafice mai rapide a subminat și mai mult poziția Java. Dar fiecare nor are o căptușeală de argint - toată această mișcare a determinat doar dezvoltatorii Java să dezvolte și să îmbunătățească bibliotecile grafice. Să vedem ce iese din asta.

Setul de instrumente pentru fereastra abstractă

AWT a fost prima încercare a lui Sun de a crea o interfață grafică pentru Java. Au luat calea ușoară și au făcut pur și simplu un strat Java care apelează metode din bibliotecile scrise în C. Metodele bibliotecii creează și folosesc componente grafice ale mediului de operare. Pe de o parte, acest lucru este bun, deoarece un program Java este similar cu alte programe din acest sistem de operare. Dar, pe de altă parte, nu există nicio garanție că diferențele de dimensiuni și fonturi ale componentelor nu vor strica aspectul programului atunci când îl rulează pe o altă platformă. În plus, pentru a asigura funcționalitatea multi-platformă, a fost necesară unificarea interfețelor de apelare a componentelor, motiv pentru care funcționalitatea acestora a fost ușor redusă. Și setul de componente s-a dovedit a fi destul de mic. De exemplu, AWT nu are tabele, iar butoanele nu acceptă afișarea pictogramelor.

AWT încearcă să elibereze automat resursele utilizate. Acest lucru adaugă un pic de complexitate arhitecturii și afectează performanța. AWT este destul de ușor de învățat, dar a scrie ceva complex va fi oarecum dificil. În zilele noastre este folosit doar pentru applet-uri.

Avantaje:

  • parte JDK;
  • viteza de lucru;
  • componentele grafice sunt similare cu cele standard.

Defecte:

  • utilizarea componentelor native impune restricții privind utilizarea proprietăților acestora. Este posibil ca unele componente să nu funcționeze deloc pe platforme non-native;
  • unele proprietăți, cum ar fi pictogramele și sfaturile instrumente, sunt complet absente în AWT;
  • Există foarte puține componente AWT standard, programatorul trebuie să implementeze multe personalizate;
  • programul arată diferit pe diferite platforme (poate fi strâmb).

concluzie:

În prezent, AWT este folosit extrem de rar - în principal în proiecte și applet-uri vechi. Oracle a ascuns tutoriale și încurajează trecerea la Swing în toate modurile posibile. Acest lucru este de înțeles; accesul direct la componentele axei poate deveni o gaură serioasă de securitate.

Leagăn


După AWT, Sun a dezvoltat un set de componente grafice numite Swing. Componentele Swing sunt scrise în întregime în Java. 2D este folosit pentru randare, ceea ce aduce cu sine mai multe avantaje. Setul de componente standard depășește semnificativ AWT ca varietate și funcționalitate. A devenit ușor să creezi noi componente, moștenind din cele existente și desenând orice dorește inima ta. Sprijinul pentru diverse stiluri și skin-uri a devenit posibil. Cu toate acestea, viteza primelor versiuni de Swing a lăsat mult de dorit. Un program scris incorect ar putea bloca complet Windows.

Cu toate acestea, datorită ușurinței sale de utilizare, documentației bogate și componentelor flexibile, Swing a devenit poate cel mai popular cadru grafic din Java. Pe baza acestuia au apărut multe extensii, precum SwingX, JGoodies, care simplifică foarte mult crearea de interfețe de utilizator complexe. Aproape toate mediile de programare Java populare includ editori grafici pentru formularele Swing. Prin urmare, înțelegerea și începerea utilizării Swing nu va fi dificilă.

Avantaje:

  • parte a JDK, nu este nevoie să instalați biblioteci suplimentare;
  • sunt multe mai multe cărți despre Swing și răspunsuri pe forumuri. Toate problemele, în special pentru începători, sunt bine cunoscute de Google;
  • editor de formulare încorporat în aproape toate mediile de dezvoltare;
  • există multe extensii bazate pe swing, cum ar fi SwingX;
  • suport pentru diferite stiluri (Look and feel).

Defecte:

  • o fereastră cu multe componente începe să încetinească;
  • Lucrul cu managerii de layout poate fi un coșmar în interfețele complexe.

Concluzie:

Swing a trăit, Swing este viu, Swing va trăi. Deși Oracle încearcă să promoveze JavaFX, Swing rămâne astăzi cel mai popular cadru pentru crearea de interfețe cu utilizatorul în Java.

Setul de instrumente Widget standard


Cum
arata
S.W.T.

SWT a fost dezvoltat de IBM într-un moment în care Swing era încă lent și a fost făcut în primul rând pentru a promova mediul de programare Eclipse. SWT, ca și AWT, utilizează componente ale sistemului de operare, dar are propriile interfețe de interacțiune pentru fiecare platformă. Deci, pentru fiecare sistem nou, va trebui să furnizați o bibliotecă JAR separată cu versiunea corespunzătoare a SWT. Acest lucru a făcut posibilă utilizarea mai completă a funcționalității existente a componentelor pe fiecare axă. Caracteristicile și componentele lipsă au fost implementate folosind 2D ca în Swing. SWT are mulți adepți, dar, mână pe inimă, nu se poate să nu fie de acord că totul s-a dovedit a nu fi atât de simplu pe cât ne-am dori. Un începător va trebui să petreacă mult mai mult timp învățând SWT decât se familiarizează cu Swing. În plus, SWT atribuie programatorului sarcina de a elibera resurse și, prin urmare, trebuie să fie deosebit de atent când scrie cod, astfel încât o excepție accidentală să nu conducă la scurgeri de memorie.

Avantaje:

  • foloseste componente ale sistemului de operare - viteza mai mare;
  • Eclipse oferă un editor de formulare vizuale;
  • documentație extinsă și multe exemple;
  • Este posibil să utilizați componente AWT și Swing.

Defecte:

  • trebuie furnizată o bibliotecă separată pentru fiecare platformă;
  • trebuie să monitorizați în mod constant utilizarea resurselor și să le eliberați în timp util;
  • arhitectură complexă care evocă gânduri sinucigașe după încercări zadarnice de a implementa o interfață personalizată.

Concluzie:

Este clar că IBM a încercat. Dar s-a dovedit a fi foarte amator...

JavaFX


JavaFX poate fi numit o descoperire fără exagerare. Conducta grafică este folosită pentru randare, ceea ce accelerează semnificativ aplicația. Setul de componente încorporate este extins, există chiar și componente separate pentru desenarea graficelor. Este implementat suport pentru conținut multimedia, multe efecte de afișare, animație și chiar multi-touch. Aspectul tuturor componentelor poate fi schimbat cu ușurință folosind stiluri CSS. Și cel mai bun lucru este că JavaFX include un set de utilități care vă permit să creați un program de instalare nativ pentru cele mai populare platforme: exe sau msi pentru Windows, deb sau rpm pentru Linux, dmg pentru Mac. Puteți găsi documentație detaliată și un număr mare de exemple gata făcute pe site-ul web Oracle. Acest lucru face programarea cu JavaFX ușoară și plăcută.

Avantaje:

  • lucru rapid datorită conductei grafice;
  • multe componente diferite;
  • suport stilistic;
  • utilitare pentru crearea unui program de instalare;
  • Aplicația poate fi lansată ca aplicație desktop și într-un browser ca parte a unei pagini.

Defecte:

  • cadrul este încă în curs de dezvoltare, așa că apar blocări și unele erori;
  • JavaFX nu este încă utilizat pe scară largă.

Concluzie:

Bună treabă, Oracle. Cadrul lasă doar impresii pozitive. Nu este greu de înțeles; metodele și interfețele par logice. Vreau să-l folosesc din nou și din nou!

Biblioteci vizuale în practică

SWT: widget meteo

Pentru a demonstra capacitățile celor mai populare biblioteci grafice și principiile de bază ale lucrului cu acestea, vom realiza mai multe widget-uri mici care afișează diverse informații.

Și să începem cu, poate, cel mai popular widget - afișarea vremii curente, pentru implementarea căreia vom alege SWT.

Orice program SWT începe prin crearea unui obiect Display. Acesta servește ca un fel de context de aplicație care conține metodele necesare pentru accesarea resurselor sistemului și oferă o buclă de evenimente. Următorul pas este crearea obiectului Shell la fel de important. Shell este o fereastră obișnuită a sistemului de operare. Afișarea este transmisă constructorului shell pentru a crea fereastra de nivel superior.

Display display = new Display(); shell = nou Shell (afișare, SWT.NO_TRIM);

Deoarece creăm un widget, nu trebuie să afișăm cadrul standard al ferestrei și butoanele de control; pentru aceasta am specificat steag-ul NO_TRIM. Pentru fundal vom folosi o imagine - un dreptunghi cu colțuri rotunjite. În principiu, o fereastră SWT poate lua orice formă. Pentru a obține acest efect, folosim clasa Regiune. Tot ce trebuie să faceți este să adăugați toate punctele vizibile din imaginea de fundal la această clasă, sărind peste cele transparente.

Încărcarea unei imagini:

Imagine imagine = imagine nouă (afișare, „images/bg.png#26759185”);

În imaginile de formate diferite, transparența este setată diferit și, prin urmare, informațiile despre zonele transparente nu sunt, de asemenea, recuperate în același mod. Creați o zonă de fundal și adăugați toate punctele vizibile acolo:

Regiune regiune = regiune nouă(); ImageData imageData = image.getImageData(); if (imageData.alphaData != null) ( Rectangle pixel = new Rectangle(0, 0, 1, 1); for (int y = 0; y< imageData.height; y++) { for (int x = 0; x < imageData.width; x++) { if (imageData.getAlpha(x, y) == 255) { pixel.x = imageData.x + x; pixel.y = imageData.y + y; region.add(pixel); } } } } else { ImageData mask = imageData.getTransparencyMask(); Rectangle pixel = new Rectangle(0, 0, 1, 1); for (int y = 0; y < mask.height; y++) { for (int x = 0; x < mask.width; x++) { if (mask.getPixel(x, y) != 0) { pixel.x = imageData.x + x; pixel.y = imageData.y + y; region.add(pixel); } } } }

Setați forma ferestrei:

Shell.setRegion(regiune);

Acum trebuie să creăm un ascultător de evenimente pentru fereastră. Vom fi interesați de evenimentele de extragere ale ferestrei, evenimentele mouse-ului și evenimentele de apăsare a tastelor, astfel încât fereastra să poată fi mutată pe ecran.

Ascultător ascultător = new Listener() ( int startX, startY; public void handleEvent(Event e) ( dacă (e.type == SWT.KeyDown && e.character == SWT.ESC) ( shell.dispose(); ) dacă (e.type == SWT.MouseDown && e.button == 1) ( startX = e.x; startY = e.y; ) dacă (e.type == SWT.MouseMove && (e.stateMask & SWT.BUTTON1) != 0 ) ( Punctul p = shell.toDisplay(e.x, e.y); p.x -= startX; p.y -= startY; shell.setLocation(p); ) if (e.type == SWT.Paint) ( ex.gc.drawImage( imagine, imageData.x, imageData.y); ) ) );

Deci, apăsând tasta Esc va închide fereastra. Când apăsați butonul stâng al mouse-ului pe o zonă a ferestrei, amintiți-vă coordonatele clicului. Când mutați mouse-ul cu tasta din stânga apăsată, mișcăm fereastra pe ecran în funcție de mișcare. Când are loc un eveniment de redesenare, desenăm o imagine de fundal folosind contextul grafic GC.

Să atribuim un ascultător evenimentelor corespunzătoare din fereastră:

Shell.addListener(SWT.KeyDown, ascultător); shell.addListener(SWT.MouseDown, ascultător); shell.addListener(SWT.MouseMove, ascultător); shell.addListener(SWT.Paint, ascultător);

Setați dimensiunea ferestrei egală cu dimensiunea imaginii:

Shell.setSize(imageData.x + imageData.width, imageData.y + imageData.height);

Deschideți o fereastră și porniți bucla de evenimente:

Shell.open(); în timp ce (!shell.isDisposed ()) ( dacă (!display.readAndDispatch ()) display.sleep (); )

Nu uitați să eliberați resursele utilizate la sfârșit:

regiune.dispose(); imagine.dispose(); display.dispose();

Prin rularea programului în această etapă, vom obține un dreptunghi care poate fi mutat cu mouse-ul și închis folosind Esc.

Este timpul să adăugați ceva conținut. Vom afișa vremea curentă sub forma unei pictograme de stare (soare, ploaie, zăpadă...), citirile de temperatură și ora ultimei actualizări.

Managerii de aspect sunt utilizați pentru a aranja componentele grafice în fereastră în forma dorită. Managerul de layout se ocupă nu numai de aranjarea componentelor, ci și de redimensionarea acestora pe măsură ce dimensiunea ferestrei se schimbă. Pentru widget-ul nostru vom folosi GridLayout. Acest manager plasează componente în celulele unui tabel imaginar. Creăm un GridBagLayout cu două coloane cu lățimi diferite de coloane (steagul fals în constructor), îl setăm ca manager de aspect de fereastră:

GridLayout layout = new GridLayout(2, false); shell.setLayout(layout);

Pentru imaginea de stare folosim componenta Label. Trecem obiectul fereastră ca părinte. Al doilea parametru poate fi folosit pentru a seta stilul componentei. Pentru fiecare componentă, setul de posibile steaguri de stil este diferit; acestea pot fi găsite în documentație sau direct în codul sursă al componentei.

//desenează imaginea de stare Label imageLabel = new Label(shell, SWT.NONE); imageLabel.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, adevărat, adevărat, 1, 1));

Steaguri din clasa GridData înseamnă că eticheta va fi poziționată în stânga sus, se va întinde pe orizontală și pe verticală (steaguri setate la adevărat) atunci când există spațiu liber și va ocupa un rând și o coloană a tabelului de aspect.

În SWT nu există un fundal transparent al componentelor, iar în spatele imaginii de stare va exista un fundal alb, care, desigur, nu ar fi de dorit. Deci, să creăm un obiect Color cu culoarea de fundal a ferestrei:

Culoare bgColor = culoare nouă (afișare, 0x2b, 0x2b, 0x2b);

La sfârșitul programului, acest obiect trebuie de asemenea eliminat prin apelarea metodei dispose. Setăm culoarea de fundal și imaginea de stare, care pot fi încărcate din fișier în același mod în care am încărcat imaginea de fundal la început:

ImageLabel.setBackground(bgColor); Stare imagineImagine = imagine nouă (afișare, „images/1.png#26759185”); imageLabel.setImage(statusImage);

Acum să adăugăm o etichetă cu temperatura curentă și să o plasăm în partea dreaptă sus a ferestrei:

Label temperatureLabel = new Label(shell, SWT.NONE); temperatureLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false, 1, 1));

Să setăm niște temperatură:

TemperatureLabel.setText("+1 \u2103");

Pentru a înregistra temperatura în Celsius, se folosește numărul Unicode al caracterului corespunzător cu caracterele de serviciu \u.

Fontul implicit pentru etichetele de text este prea mic. Deci, să creăm unul nou, mai mare:

FontData fD = temperatureLabel.getFont().getFontData(); fD.setHeight(30); fD.setStyle(SWT.BOLD); Font newFont = font nou (afișare, fD); temperatureLabel.setFont(newFont); Fontul, ca și alte obiecte de resurse, trebuie eliberat. Pentru a face acest lucru, vom folosi un ascultător de evenimente de distrugere a etichetei:

TemperatureLabel.addDisposeListener(new DisposeListener() ( public void widgetDisposed(DisposeEvent e) ( newFont.dispose(); ) ));

În cele din urmă, să adăugăm o etichetă care descrie condițiile meteorologice:

Label descriptionLabel = new Label(shell, SWT.WRAP); descriptionLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 2, 1)); descriptionLabel.setText("Parțial noros, ploaie slabă"); descriptionLabel.setBackground(bgColor); descriptionLabel.setForeground(display.getSystemColor(SWT.COLOR_WHITE));

Textul poate fi destul de lung, așa că atunci când creăm o etichetă, specificăm steag-ul WRAP astfel încât textul să fie rupt automat în mai multe rânduri dacă nu este suficient spațiu. Să asezăm componenta în centru și să-i lăsăm să umple întreg spațiul orizontal. De asemenea, subliniem că componenta ocupă două coloane din tabelul de layout. Lansăm și obținem fereastra din imaginea „Weather Widget”.

Acum puteți atașa un serviciu meteo, puteți crea un cronometru pentru actualizarea automată - și widget-ul este gata.

Swing: întotdeauna cele mai recente știri

Vom scrie un widget în Swing pentru a afișa fluxuri RSS. Începem, ca data trecută, prin a crea o fereastră. Clasa care implementează funcționalitatea unei ferestre standard în Swing se numește JFrame. În mod implicit, închiderea unei ferestre de aplicație în Swing nu determină oprirea programului, deci este mai bine să specificați cum ar trebui să se comporte fereastra când este închisă:

JFrame frame = nou JFrame(); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

Un tabel este cel mai bun pentru prezentarea știrilor. Swing este construit pe modelul Model-View-Controller (MVC). În arhitectura MVC, modelul furnizează datele, vizualizarea este responsabilă pentru afișarea datelor (de exemplu, text, câmpuri de intrare), iar controlerul asigură interacțiunea între model și vizualizare. Tabelul demonstrează bine această abordare. Pentru a reprezenta datele, se folosește o clasă care implementează interfața TableModel.

Pentru a stoca informații despre știrile disponibile, să creăm o clasă FeedMessage cu câmpuri pentru titlul articolului și data publicării:

Clasa publică FeedMessage ( titlu public String; public Data publicationDate; )

Pentru a simplifica și accelera dezvoltarea, moștenim modelul nostru de date din clasa AbstractTableModel, care oferă o implementare gata făcută a aproape tuturor metodelor interfeței TableModel.

Clasa publică RssFeedTableModel extinde AbstractTableModel (listă privată entries = new ArrayList<>(); public void updateData(Lista intrări) ( this.entries = entries; fireTableDataChanged(); ) public int getRowCount() ( return entries.size(); ) public int getColumnCount() ( return 2; ) public Object getValueAt(int rowIndex, int columnIndex) ( comutator (columnIndex) (cazul 0: returnează intrări.get(rowIndex).title; cazul 1: returnează entries.get(rowIndex).publicationDate; ) return null; ) )

Metoda fireTableDataChanged spune vederii că modelul de date s-a schimbat și trebuie redesenat.

Creăm un tabel și îi schimbăm puțin aspectul, astfel încât să arate mai mult ca un widget. Îndepărtăm liniile dintre rânduri și coloane, creștem înălțimea rândului și eliminăm antetul tabelului cu numele coloanelor:

JTable table = new JTable(new RssFeedTableModel()); table.setShowGrid(false); table.setIntercellSpacing(new Dimension(0, 0)); table.setRowHeight(30); table.setTableHeader(null);

Acum să ne uităm la aspectul celulelor. Swing vă permite să atribuiți clase de vizualizare separate pentru diferite tipuri de date. O clasă care moștenește interfața TableCellRenderer este responsabilă pentru redarea celulelor individuale ale tabelului. Valoarea implicită este DefaultTableCellRenderer, care este o etichetă text.

Să atribuim redarea celulelor noastre datelor de tip String. Să schimbăm culoarea implicită a fontului și să facem alternativă culoarea de fundal pentru a îmbunătăți lizibilitatea.

Table.setDefaultRenderer(String.class, new DefaultTableCellRenderer() ( Color oddColor = new Color(0x25, 0x25, 0x25); Color evenColor = new Color(0x1a, 0x1a, 0x1a); Color titleColor = new Color(0x3a, 0dxa2, 0dxa2 ); Componentă publică getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) ( super.getTableCellRendererComponent(tabel, valoare, isSelected, hasFocus, row, column); setBackground(row % 2 == 0 ? oddColor: evenColor); setForeground(titleColor); setFont(font); return this; ) ));

Pentru ca tabelul să înceapă să folosească redarea noastră, trebuie să adăugăm o metodă care returnează tipul de date pentru fiecare celulă la modelul de date:

Clasa publicăgetColumnClass(int columnIndex) ( switch (columnIndex) (cazul 0: returnează String.class; cazul 1: return Date.class; ) return Object.class; )

Pot fi o mulțime de știri, așa că haideți să plasăm tabelul pe bara de defilare și să facem glisorul de defilare invizibil, astfel încât să nu strice designul widget-ului:

JScrollPane scrollPane = nou JScrollPane(tabel); table.setFillsViewportHeight(true); scrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(0,0));

Adăugați o componentă de defilare în panoul principal al ferestrei. Al doilea argument poate fi plasarea componentei. În mod implicit, panoul principal al ferestrei folosește managerul de aspect BorderLayout, care aranjează componentele conform direcțiilor cardinale. Să punem o masă cu derulare în centru.

Frame.getContentPane().add(scrollPane, BorderLayout.CENTER);

Ca și data trecută, vom elimina cadrul standard al ferestrei. Și ca titlu al ferestrei vom folosi o etichetă de text stilizată, pe care o vom plasa în partea de sus a ferestrei.

JLabel titleLabel = new JLabel ("Xakep RSS"); Font titleFont = font nou ("Arial", Font.BOLD, 20); titleLabel.setFont(titleFont); titleLabel.setHorizontalAlignment(SwingConstants.CENTER); titleLabel.setForeground(Color.WHITE); titleLabel.setPreferredSize(new Dimension(0, 40)); frame.getContentPane().add(titleLabel, BorderLayout.NORTH);

Spre deosebire de SWT, obiectele de culoare și font sunt eliberate automat, astfel încât nu mai trebuie să vă faceți griji cu privire la scurgerile de memorie.

Adăugați ascultători de mouse, astfel încât fereastra să poată fi mutată pe ecran.

Ascultător MouseAdapter = nou MouseAdapter() ( int startX; int startY; public void mousePressed(MouseEvent e) ( dacă (e.getButton() == MouseEvent.BUTTON1) ( startX = e.getX(); startY = e.getY( ); ) ) public void mouseDragged(MouseEvent e) ( Point currCoords = e.getLocationOnScreen(); frame.setLocation(currCoords.x - startX, currCoords.y - startY); ) ); titleLabel.addMouseListener(ascultător); titleLabel.addMouseMotionListener(ascultător);

Acum să schimbăm forma ferestrei într-un dreptunghi cu colțuri rotunjite. Cel mai bine este să faceți acest lucru într-un ascultător de componentă, deoarece dacă dimensiunea ferestrei se schimbă, forma ferestrei va fi recalculată corect:

Frame.addComponentListener(new ComponentAdapter() ( public void componentResized(ComponentEvent e) ( frame.setShape(new RoundRectangle2D.Double(0, 0, frame.getWidth(), frame.getHeight(), 20, 20)); ) ) );

Setați dimensiunea ferestrei, îndepărtați cadrul și faceți fereastra translucidă.

Frame.setSize(520, 300); frame.setUndecorated(true); frame.setOpacity(0.85f);

În cele din urmă, deschidem fereastra în fluxul grafic. SwingUtilities.invokeLater(new Runnable() ( public void run() ( frame.setVisible(true); ) ));

Tot ce rămâne este să adăugați încărcarea datelor într-un fir separat și vom primi un widget ca acesta cu cele mai recente știri din revista dvs. preferată :).


JavaFX: hai să ascultăm niște muzică

Și, în sfârșit, punctul culminant al sezonului este JavaFX. Să folosim capacitățile și componenta multimedia pentru a trasa și să facem un egalizator simplu.

În primul rând, moștenim clasa widget-ului de la Application. Aceasta este clasa principală de aplicații din JavaFX. Aplicația conține principalele metode ale ciclului de viață al aplicației. Componentele formularului sunt create în metoda start, care ia ca argument clasa Stage. Stage este o fereastră de program. Să schimbăm stilul ferestrei în TRANSPARENT pentru a elimina chenarul și butoanele. Scena conține clasa Scenă, care stabilește dimensiunea ferestrei și culoarea de fundal. În Scene, la rândul nostru, trecem clasa Group, în care vom plasa componente copil:

Public void start(Stage primaryStage) ( primaryStage.initStyle(StageStyle.TRANSPARENT); Group root = new Group(); Scene scene = new Scene(root, 400, 200, Color.TRANSPARENT); primaryStage.setScene(scene);

Pentru a afișa egalizatorul, folosim un grafic cu bare, de-a lungul axelor căruia vom afișa frecvența și puterea sunetului:

CategoryAxis xAxis = new CategoryAxis(); NumberAxis yAxis = new NumberAxis(0,50,10); BarChart bc = BarChart nou (Axa x,Axa y); bc.setPrefSize(400, 200); bc.setLegendVisible(false); bc.setAnimated(false); bc.setBarGap(0); bc.setCategoryGap(1); bc.setVerticalGridLinesVisible(false); bc.setHorizontalGridLinesVisible(false); xAxis.setLabel("Frecventa"); yAxis.setLabel("Putere"); yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis, null, "dB"));

Completați diagrama cu datele inițiale:

XYChart.Series series1 = nou XYChart.Series (); series1Data = noi XYChart.Data; Categorii de șiruri = String nou; pentru (int i=0; i (categorii[i], 50); series1.getData().add(series1Data[i]); ) bc.getData().add(series1);

Creați un dreptunghi cu colțuri rotunjite pentru a da widget-ului forma corespunzătoare:

dreptunghi dreptunghi = new Rectangle(0, 0, 400, 200); Stop stops = new Stop ( new Stop(0, new Color(0, 0, 0, 0.8)), null); LinearGradient lg2 = new LinearGradient(0, 0, 0, 0, false, CycleMethod.NO_CYCLE, stops); dreptunghi.setFill(lg2); dreptunghi.setArcHeight(20); dreptunghi.setArcWidth(20);

Adăugați ambele componente la grup:

Root.getChildren().addAll(dreptunghi, bc);

Atribuim ascultătorii mouse-ului unui grup pentru a muta fereastra în jurul ecranului:

Root.setOnMousePressed (noul EventHandler () ( public void handle(MouseEvent me) ( initX = me.getScreenX() - primaryStage.getX(); initY = me.getScreenY() - primaryStage.getY(); ) )); root.setOnMouseDragged(noul EventHandler () ( public void handle(MouseEvent me) ( primaryStage.setX(me.getScreenX() - initX); primaryStage.setY(me.getScreenY() - initY); ) ));

Încărcați melodia în player:

Fișier fișier = fișier nou(„scoate-mă de aici.mp3”); Media audioMedia = null; audioMedia = new Media(file.toURI().toURL().toString()); audioMediaPlayer = nou MediaPlayer(audioMedia);

Adăugați un ascultător care va actualiza diagrama cu bare:

AudioMediaPlayer.setAudioSpectrumListener(new AudioSpectrumListener() (public void spectrumDataUpdate(dublu timestamp, durată dublă, mărimi float, faze float) (pentru (int i = 0; i< series1Data.length; i++) { series1Data[i].setYValue(magnitudes[i] + 60); } } });

Faceți scena vizibilă și începeți cântecul:

PrimaryStage.show(); audioMediaPlayer.play();

Lansați aplicația:

Public static void main(String args) ( lansare(args); )

Și ne bucurăm de o asemenea frumusețe.

Interfața grafică din Java a trecut printr-o cale foarte spinoasă de dezvoltare și formare. Multă vreme a fost acuzat că este lent, avid de resurse de sistem și funcționalitate limitată.

Java AWT

Prima încercare a lui Sun de a crea un GUI pentru Java a fost biblioteca A.W.T.(Abstract Window Toolkit) - un set de instrumente pentru lucrul cu diferite medii de ferestre. Sun a realizat un strat Java care apelează metode din biblioteci scrise în C. Metodele bibliotecii AWT creează și utilizează componente grafice ale mediului de operare. Pe de o parte, acest lucru este bun, deoarece un program Java este similar cu alte programe din același sistem de operare. Dar atunci când îl rulați pe o altă platformă, pot exista diferențe de dimensiuni ale componentelor și fonturilor care vor strica aspectul programului.

Pentru a asigura multi-platformă A.W.T. Interfețele de apel ale componentelor au fost unificate, drept urmare funcționalitatea lor a fost ușor redusă. Și setul de componente s-a dovedit a fi destul de mic. De exemplu, AWT nu are tabele, iar butoanele nu acceptă afișarea pictogramelor. Tot pachetul java.awt a fost inclus în Java încă de la prima sa lansare și poate fi folosit pentru a crea interfețe grafice.

Deci componentele A.W.T. Ei nu fac nicio „muncă”. Este pur și simplu un „înveliș Java” pentru controalele sistemului de operare pe care rulează. Toate solicitările către aceste componente sunt redirecționate către sistemul de operare, care face toată munca.

Resurse folosite A.W.T.încearcă să se elibereze automat. Acest lucru adaugă un pic de complexitate arhitecturii și afectează performanța. Va fi oarecum dificil să scrii ceva serios folosind AWT. În zilele noastre este folosit doar pentru applet-uri.

Concepte de bază ale SWING

După A.W.T. Sun a dezvoltat o bibliotecă de componente grafice Leagăn, scris în întregime în Java. 2D este folosit pentru randare, ceea ce aduce cu sine mai multe avantaje. Setul de componente standard depășește semnificativ AWT ca varietate și funcționalitate. Swing facilitează crearea de noi componente prin moștenirea celor existente și acceptă diferite stiluri și skin-uri.

Creatorii unei noi biblioteci de interfață cu utilizatorul Leagăn Nu au „reinventat roata” și au ales AWT ca bază pentru biblioteca lor. Desigur, nu vorbeam despre utilizarea unor componente AWT grele specifice (reprezentate de clasele Button, Label și altele asemenea). Doar componentele ușoare au oferit gradul necesar de flexibilitate și control. Diagrama de moștenire arată relația dintre AWT și Swing.

Cea mai importantă diferență Leagăn de la AWT este că componentele Swing nu sunt deloc cuplate la sistemul de operare și, prin urmare, sunt mult mai stabile și rapide. Aceste componente sunt numite „lightweights” în Java, iar înțelegerea principiilor de bază ale modului în care funcționează va contribui în mare măsură la explicarea modului în care funcționează Swing.

Containere balansate de cel mai înalt nivel

Pentru a crea o aplicație GUI, trebuie să utilizați componente speciale ale bibliotecii Swing numite containere de nivel superior. Sunt ferestre ale sistemului de operare care adăpostesc componente ale interfeței cu utilizatorul. Containerele de nivel superior includ ferestrele JFrame și JWindow, caseta de dialog JDialog și applet-ul JApplet (care nu este o fereastră, dar este proiectat și pentru a afișa interfața în browserul care lansează acest applet). Containerele de top Swing sunt componente grele și fac excepție de la regula generală. Toate celelalte componente Swing sunt ușoare.

Simplu Leagăn exemplu de creare a unei interfețe de fereastră JFrame.

Import java.awt.Dimension; import javax.swing.JFrame; import javax.swing.JLabel; clasă publică JFrameTest ( public static void createGUI() ( JFrame frame = new JFrame("Test frame"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JLabel label = new JLabel ("Test label"); frame.getContentPane(). add(label); frame.setPreferredSize(new Dimension(200, 100)); frame.pack(); frame.setVisible(true); ) public static void main(String args) ( JFrame.setDefaultLookAndFeelDecorated(true); javax. swing.SwingUtilities.invokeLater(new Runnable() ( public void run() ( createGUI(); ) )); ) )

Constructor JFrame() fără parametri creează o fereastră goală. Constructor JFrame (titlu șir) creează o fereastră goală cu titlul titlului. Pentru a crea un program simplu cu o fereastră goală, trebuie să utilizați următoarele metode:

  • setSize(int width, int height) - determinarea dimensiunii ferestrei;
  • setDefaultCloseOperation(int operation) - definirea acțiunii când programul se termină;
  • setVisible(boolean vizibil) - face fereastra vizibilă.

Dacă nu definiți dimensiunile unei ferestre, aceasta va avea înălțime zero indiferent de ce se află în ea. Dimensiunile ferestrei includ nu numai zona „de lucru”, ci și chenarele și bara de titlu.

Metoda setDefaultCloseOperation specifică acțiunea care trebuie efectuată atunci când „programul iese”. Pentru a face acest lucru, ar trebui să treceți constanta EXIT_ON_CLOSE, descrisă în clasa JFrame, ca parametru de operare.

În mod implicit, fereastra este creată invizibilă. Pentru a afișa fereastra pe ecran, metoda setVisible este apelată cu parametrul true. Dacă este apelată cu parametrul false, fereastra va deveni invizibilă.

GUI leagăn java exemplu de creare a unei ferestre JFrame este prezentată în figura următoare.

Pentru a conecta biblioteca Leagăn aplicația trebuie să importe biblioteca javax.swing.

De fiecare dată când este creat un container de nivel superior, fie că este o fereastră obișnuită, o casetă de dialog sau un applet, a panoul rădăcină JRootPane. Containerele de nivel superior Swing asigură că alte componente nu pot ieși în afara JRootPane.

Rădăcină palel JRootPane adaugă proprietatea „adâncime” containerelor, oferind capacitatea nu numai de a plasa componentele una peste alta, ci și, dacă este necesar, de a-și schimba locurile, de a crește sau de a reduce adâncimea componentelor. Această caracteristică este necesară la crearea unei aplicații cu mai multe documente. Leagăn, în care ferestrele reprezintă componente ușoare situate una peste alta, precum și meniuri derulante (contextuale) și sfaturi cu instrumente.

Următoarea figură arată clar structura panoului rădăcină JRootPane.

Panoul rădăcină JRootPane este un container moștenit din clasa de bază Swing JComponent. În acest container, un manager special de layout, implementat în clasa internă RootPaneLayout, este responsabil pentru aranjarea componentelor. Acest manager de layout este responsabil pentru a se asigura că toate părțile componente ale panoului rădăcină sunt plasate așa cum ar trebui: un panou stratificat ocupă întreg spațiul ferestrei; stratul său FRAME_CONTENT_LAYER conține bara de meniu și panoul de conținut, iar mai presus de toate acestea există un panou transparent.

Toate componentele panoului rădăcină JRootPane pot fi obținute sau modificate. Pentru a face acest lucru, are un set de metode get/set. Din punct de vedere programatic JRootPane poate fi obținut folosind metoda getRootPane().

În plus față de containerele de nivel superior, panoul rădăcină este utilizat în ferestrele interne JInternalFrame create în aplicații cu mai multe documente și situate pe „desktop” JDesktopPane. Acest lucru vă permite să uitați de faptul că aceste ferestre sunt componente ușoare obișnuite și să lucrați cu ele ca și cum ar fi adevărate containere de nivel superior.

JLayeredPane

La baza panoului rădăcină (container) se află așa-numitul panou cu mai multe straturi JLayeredPane, ocupând tot spațiul disponibil al containerului. În acest panou se află toate celelalte părți ale panoului rădăcină, inclusiv toate componentele interfeței cu utilizatorul.

JLayeredPane folosit pentru a adăuga o proprietate de adâncime la container. Adică, un panou cu mai multe straturi vă permite să organizați o a treia dimensiune în container, de-a lungul căreia sunt situate straturile componentei. Într-un container obișnuit, locația unei componente este determinată de un dreptunghi care arată cât de mult din container ocupă componenta. Când adăugați o componentă la un panou stratificat, trebuie să specificați nu numai dreptunghiul pe care îl va ocupa componenta, ci și stratul în care va fi amplasată. Stratul dintr-un panou sandwich este identificat printr-un număr întreg. Cu cât este mai mare numărul care definește un strat, cu atât stratul este situat mai sus.

Prima componentă adăugată în container este clasată mai sus decât componentele adăugate ulterior. Cel mai adesea, dezvoltatorul nu se ocupă de pozițiile componentelor. Când adăugați componente, poziția acestora se schimbă automat. Cu toate acestea, un panou cu mai multe straturi vă permite să schimbați poziția componentelor în mod dinamic, după ce acestea sunt adăugate în container.

Capacitățile panourilor laminate sunt utilizate pe scară largă de unele componente Leagăn. Ele sunt deosebit de importante pentru aplicațiile cu mai multe documente, sfaturi de instrumente și meniuri. Multi-document Leagăn aplicațiile folosesc un container special JDesktopPane(„desktop”), moștenit de la JLayeredPane, care adăpostește ferestrele interioare Swing. Cele mai importante funcții ale unei aplicații cu mai multe documente - plasarea ferestrei „active” peste altele, minimizarea ferestrelor, tragerea lor - sunt asigurate de mecanismele panoului stratificat. Principalul beneficiu al utilizării unui panou stratificat pentru sfaturi și meniuri este că funcționează mai rapid. În loc să creați o nouă fereastră grea pentru fiecare sfat explicativ sau meniu care se află deasupra componentei care a solicitat indicația sau meniul, Leagăn creează o componentă rapidă și ușoară. Această componentă este plasată suficient de sus în panoul stratificat deasupra stivei tuturor celorlalte componente și este folosită pentru a afișa un sfat explicativ sau un meniu.

Panoul multistrat vă permite să organizați un număr nelimitat de straturi. Structura JLayeredPane include mai multe straturi standard, care sunt utilizate de toate componentele Swing, ceea ce asigură funcționarea corectă a tuturor mecanismelor panoului multistrat. Straturile standard JLayeredPane sunt prezentate în figura următoare.

Stratul implicit este folosit pentru a găzdui toate componentele normale care sunt adăugate containerului. Acest strat găzduiește ferestrele interne ale aplicațiilor cu mai multe documente.

Stratul Paletă este conceput pentru a găzdui ferestre cu un set de instrumente, care de obicei se suprapun cu alte elemente de interfață. Puteți crea astfel de ferestre folosind JDesktopPane, care le plasează pe acest strat.

Stratul Modal a fost destinat să găzduiască casete de dialog modale ușoare. Cu toate acestea, astfel de casete de dialog nu sunt încă implementate, astfel încât acest strat nu este utilizat în prezent în Swing.

Stratul cel mai frecvent utilizat pentru plasarea meniurilor pop-up și sfaturi cu instrumente.

Stratul cel mai de sus. Proiectat pentru operațiuni de glisare și plasare care ar trebui să fie clar vizibile în interfața programului.

Un mic exemplu de JLayeredPane cu un panou stratificat arată cum să adăugați componente la diferite straturi și cum straturile sunt stivuite unul peste altul:

Import javax.swing.*; import java.awt.*; // clasă pentru desenarea a două tipuri de figuri cu clasa de text Figure extinde JComponent ( private static final long serialVersionUID = 1L; private Color color; private int type; private String text; // parametri: culoare și tipul figurii Figure(Color color, int tip, String text) ( this.color = color; this.type = type; this.text = text; setOpaque(false); ) public void paintComponent(Graphics g) ( // desenează figura g.setColor(culoare) ; comutator (tip) (case 0: g.fillOval(0, 0, 90, 90); break; case 1: g.fillRect(0, 0, 130, 80); break; ) g.setColor(Color.yellow ); g. drawString(text, 10, 35); ) ) clasă publică JLayeredPaneTest extinde JFrame (privat static final long serialVersionUID = 1L; public JLayeredPaneTest() ( // creează o fereastră super ("Exemplu LayeredTest"); // ieșire la închiderea ferestrei setDefaultCloseOperation( EXIT_ON_CLOSE); // definirea unui panou cu mai multe straturi JLayeredPane lp = getLayeredPane(); // crearea a trei figuri Figure figure1 = new Figure(Color.red , 0, "Figure popup"); Figura figura2 = Figura nouă (Color.blue, 0, "Figura 1"); Figura figura 3 = Figura nouă (Color.cyan, 1, "Figura 2"); // determinarea locației figurilor în fereastra figure1.setBounds(10, 40, 120, 120); figure2.setBounds(60, 120, 160, 180); figura3.setBounds(90, 55, 250, 180); // adăugarea de forme la diferite straturi lp.add(figure1, JLayeredPane.POPUP_LAYER); lp.add(figura2, JLayeredPane.PALETTE_LAYER); lp.add(figura3, JLayeredPane.PALETTE_LAYER); // schimbarea poziției uneia dintre figurile lp.setPosition(figure3, 0); // se determină dimensiunea și se deschide fereastra setSize(280, 250); setVisible(true); ) public static void main(String args) ( JFrame.setDefaultLookAndFeelDecorated(true); nou JLayeredPaneTest(); ) )

Exemplul creează o fereastră mică JFrameși mai multe componente Figure sunt adăugate la panoul stratificat. Pentru a obține un panou stratificat în orice container Swing de nivel superior, trebuie doar să apelați metoda getLayeredPane().

Clasa auxiliară Figure moștenește proprietățile clasei de bază JComponent și vă permite să desenați două tipuri de forme (cercuri și dreptunghiuri) în culori diferite. Parametrii pentru desenarea figurilor sunt stabiliți în constructorul clasei.

La definirea unei interfețe, sunt create trei forme de culori diferite (două cercuri și un dreptunghi). Cercul este plasat în stratul POPUP_LAYER, iar dreptunghiurile sunt plasate în stratul PALETTE_LAYER. Când plasați componente, specificați coordonatele absolute ale ecranului, deoarece managerii obișnuiți de aspect nu lucrează într-un panou stratificat.

În cele din urmă, poziția unuia dintre dreptunghiuri este schimbată astfel încât să fie primul din strat, deși inițial a fost adăugat al doilea. Când lansați aplicația, veți vedea că panoul stratificat funcționează și aranjează frumos componentele în funcție de straturile și pozițiile lor.

În aplicațiile convenționale, panoul sandwich este rar folosit direct, în care își îndeplinește funcțiile în mod invizibil. Cu toate acestea, uneori ajută la crearea de efecte uimitoare și interfețe neobișnuite, permițând, de exemplu, să plasați animații sau videoclipuri deasupra componentelor obișnuite, fără a necesita eforturi și trucuri supraomenești din partea dezvoltatorului.

ContentPane

Panoul de conținut ContentPane este următoarea parte a panoului rădăcină, care este folosită pentru a găzdui componentele interfeței cu utilizatorul ale programului. ContentPane ocupă cea mai mare parte a spațiului unui panou stratificat (cu excepția spațiului ocupat de bara de meniu). Pentru a preveni ca panoul de conținut să ascundă componentele care sunt adăugate ulterior în fereastră, panoul stratificat îl plasează într-un strat special, foarte jos, numit FRAME_CONTENT_LAYER, numerotat -30000.

Puteți accesa panoul de conținut folosind metoda getContentPane() clasa JFrame. Folosind metoda add(Component component), îi puteți adăuga orice element de control. A inlocui ContentPane cu orice alt panou de tip JPanel puteți folosi metoda setContentPane()

Exemplu de adăugare a unui buton la panoul de conținut:

JButton newButton = nou JButton(); getContentPane().add(newButton);

Ca rezultat, obținem o fereastră cu un buton. Butonul ocupă întreaga zonă disponibilă a ferestrei. Acest efect nu este util în toate programele, așa că este necesar să folosiți diferite moduri de aranjare a elementelor pe panou.

Panoul de conținut poate fi înlocuit complet. Luați în considerare următoarele Leagăn exemplu de utilizare a panoului de conținut ContentPane.

Import javax.swing.*; clasă publică ContentPaneReplace extinde JFrame (privat static final long serialVersionUID = 1L; public ContentPaneReplace() ( super("Test ContentPane"); setDefaultCloseOperation(EXIT_ON_CLOSE); // Creați un panou cu două butoane JPanel contents = new JPanel(); conținut. add (nou JButton(„Familie”)); contents.add(new JButton(„Școala”)); // Înlocuirea panoului de conținut setContentPane(conținut); // Determinarea dimensiunii ferestrei setSize(200, 100); // Deschiderea ferestrei setVisible (true); ) public static void main(String args) ( JFrame.setDefaultLookAndFeelDecorated(true); new ContentPaneAdd(); ) )

Exemplul creează o fereastră mică și un panou cu două butoane, care este apoi setContentPane()înlocuiește panoul de conținut al ferestrei. Astfel, a fost folosită o înlocuire în loc de o adăugare mai simplă - apelând metoda add(). Interfața ferestrei este afișată în următoarea captură de ecran.

Panoul de conținut ContentPaneîn sine nu este nimic special. Trebuie doar să rețineți că componentele sunt adăugate în mod special.

JOptionPane transparent

Panou transparent JOptionPane plasat ca panou rădăcină deasupra tuturor elementelor panoului multistrat. Amplasarea JOptionPane este controlată de panoul rădăcină, care plasează panoul transparent deasupra panoului stratificat, astfel încât să acopere complet întreaga zonă a ferestrei, inclusiv zona ocupată de bara de meniu.

JOptionPane Este rar folosit în aplicații, așa că în mod implicit panoul rădăcină îl face invizibil, ceea ce reduce sarcina asupra sistemului de desen. Un lucru de reținut este că, dacă faceți vizibil un panou transparent, trebuie să vă asigurați că este transparent (proprietatea sa opace este setată la false), deoarece altfel va ascunde toate celelalte elemente ale panoului rădăcină și restul interfața va fi invizibilă.

În ce cazuri se poate folosi un panou transparent? JOptionPane? Cu ajutorul acestuia, puteți identifica funcțiile aplicației care ar necesita un efort serios pentru a fi implementate de la zero. Panoul transparent poate fi adaptat pentru testarea automată a interfeței cu utilizatorul. Evenimentele sintetizate în acesta vă permit să urmăriți rezultatele intermediare de depanare. Uneori, această abordare este mult mai eficientă decât testarea manuală.

Panou transparent JOptionPane poate fi folosit pentru o animație cool pentru a „pluti” deasupra tuturor componentelor, inclusiv bara de meniu, sau pentru a intercepta evenimente dacă unele dintre ele trebuie procesate înainte de a fi trimise în partea principală a interfeței de utilizare.

Exemplu de utilizare a unui Swing JOptionPane transparent:

// Folosind un panou transparent JOptionPane import java.awt.Dimension; import java.awt.Font; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.UIManager; clasă publică JOptionPaneTest extinde JFrame ( private static final long serialVersionUID = 1L; public static final Font FONT = new Font("Verdana", Font.PLAIN, 11); public static void createGUI() ( JFrame frame = new JFrame ("Test JOptionPane "); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.addWindowListener(new WindowListener() ( public void windowActivated(WindowEvent event) () public void windowClosed(WindowEvent event) () public void windowDeactivated(WindowEvent) () public void windowDeactivated(WindowEvent) windowDeiconified(WindowEvent event) () public void windowIconified(WindowEvent event) () public void windowOpened(WindowEvent event) () public void windowClosing(WindowEvent event) (Opțiuni obiect = ( „Da”, „Nu!”); int rc = JOptionPane.showOptionDialog(event.getWindow(), „Închide fereastra?”, „Confirmare”, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, opțiuni, opțiuni); dacă (rc == 0) ( event.getWindow().setVisible (fals); System.exit(0); ) ) )); JLabel label = new JLabel ("Folosiți panoul transparent când închideți fereastra"); frame.getContentPane().add(label); frame.setPreferredSize(new Dimension(350, 80)); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); ) public static void main(String args) ( javax.swing.SwingUtilities.invokeLater(new Runnable() ( public void run() ( UIManager.put("Button.font", FONT); UIManager.put("Label.font") ", FONT); JFrame.setDefaultLookAndFeelDecorated(true); JDialog.setDefaultLookAndFeelDecorated(true); createGUI(); ) )); ) )

Dacă treceți o constantă metodei setDefaultCloseOperation JFrame.EXIT_ON_CLOSE, apoi când fereastra este închisă, aplicația nu va mai funcționa. În exemplu, o constantă este transmisă acestei metode JFrame.DO_NOTHING_ON_CLOSE ca să nu se întâmple nimic când fereastra este închisă. Aplicația din exemplu este ieșită din ascultătorul JFrame WindowListener din metodă Închiderea ferestrei. Când o fereastră este închisă, metoda windowClosing este apelată cu parametrul eveniment WindowEvent, care în Swing JOptionPane transparent deschide un dialog de confirmare.

Următoarea captură de ecran arată două ferestre de aplicație. Fereastra principală de sus. Când închideți această fereastră, se deschide caseta de dialog inferioară de confirmare a intenției.

Bara de meniu JMenuBar

Una dintre caracteristicile importante ale utilizării JRootPane în Swing este necesitatea de a plasa o bară de meniu în fereastră JMenuBar. O aplicație serioasă nu poate fi construită fără un fel de meniu pentru a accesa funcțiile programului. Biblioteca Swing oferă capabilități excelente pentru crearea de meniuri JMenuBar ușor de utilizat, care sunt, de asemenea, componente ușoare.

Bară de meniu JMenuBar este plasat într-un panou multistrat într-un strat special FRAME_CONTENT_LAYER și ocupă un spațiu mic în partea de sus a ferestrei. Lungimea barei de meniu este egală cu dimensiunea ferestrei. Lățimea barei de meniu depinde de componentele pe care le conține.

Panoul rădăcină asigură că panoul de conținut și bara de meniu JMenuBar nu s-au suprapus. Dacă nu este necesară o bară de meniu, atunci panoul rădăcină folosește tot spațiul pentru a găzdui panoul de conținut.

Exemple de leagăn

Codurile sursă ale exemplelor discutate în textul paginii pot fi descărcate.

Preaviz

Spre deosebire de orele anterioare, unde practic am acționat pe principiul „face as I do” și am vorbit despre concepte și detalii tehnice „pe degete”, stilul de prezentare, începând de la această lecție, se va schimba oarecum și va fi mai tehnic.

Acest lucru, din păcate, nu poate fi evitat, pentru că... mai devreme sau mai târziu va trebui să ajungem la un punct după care abordarea de „limsul degetelor” devine insuportabilă. Acum vine un asemenea moment. Așa că haideți să ne adunăm curaj, să ne suflecăm mânecile și să începem.

În lecția anterioară (), am creat și afișat o fereastră grafică pe ecranul monitorului și am rezolvat simultan câteva probleme privind aspectul și locația acesteia. Acum vom discuta despre ceea ce rămâne „în culise”.

Probabil ați observat că la începutul codului sursă există următoarele două rânduri:

import java.awt.*;

import javax.swing.*;

Aici trebuie să zăbovim puțin. Amintiți-vă că am menționat mai devreme că mediul de programare Java include multe biblioteci concepute pentru a suporta rețele, grafică, baze de date, mesagerie etc. Bibliotecile sunt cele care oferă Java toată puterea și versatilitatea sa.

În Java, termenul „bibliotecă” este folosit în locul termenului „pachet”. Liniile de mai sus conectează doar pachetele necesare pentru a crea o interfață grafică. Mai târziu veți vedea că vom folosi și alte pachete, dar deocamdată acestea două ne sunt suficiente.

Pachetele includ clasele și interfețele necesare (vom vorbi despre interfețe în timp util) care oferă una sau alta funcționalitate a viitoarei aplicații. Prezența unui asterisc (“*”) indică faptul că programatorul importă întregul conținut al pachetului, fără a specifica clasele sau interfețele exacte incluse în acesta. Cu pachete mari poate părea că codul obiect rezultat poate fi prea mare, dar nu vă faceți griji: compilatorul Java este suficient de inteligent pentru a utiliza doar ceea ce are nevoie programul dvs.; Compilatorul pur și simplu nu va include tot ceea ce programul nu are nevoie în codul obiect. Dacă doriți, puteți utiliza o formă ușor diferită de conexiune la pachet, de exemplu,

import java.awt.Window;

import javax.swing.JFrame;

dar aceasta presupune că programatorul are deja o bună cunoaștere a structurii și capabilităților acestor pachete. Vom folosi forma mai simplă de conectare a pachetelor indicată mai devreme.

Importarea (conectarea) unui pachet la programul în curs de dezvoltare se face folosind cuvântul cheie import, urmat de numele pachetului. Fiecare pachet trebuie importat separat (adică nu puteți scrie import java.awt.*, javax.swing.*;). Desigur, volumul codului sursă crește oarecum, dar foarte puțin. Toate clasele și interfețele care compun programul dvs. trebuie să apară strict după constructele de import, altfel compilatorul va genera un mesaj de eroare de compilare.

Primul pachet (începând cu java.awt) oferă în primul rând interacțiunea între programele Java și subsistemul grafic al sistemului de operare. Rețineți că Java este un limbaj de programare multiplatformă și generează un singur cod obiect, indiferent de sistemul de operare pe care va fi executat codul. Prin urmare, Java este „forțat” să acceseze resursele furnizate de sistemul de operare care este instalat pe computerul utilizatorului. O astfel de resursă este grafica (pe lângă grafică, Java accesează „servicii” sistemului de operare pentru a accesa sistemul de fișiere și alte resurse). Deci, pachetul java.awt.* permite interfețelor grafice scrise în Java să utilizeze capacitățile grafice ale sistemului de operare și să afișeze pe ecranul monitorului obiecte grafice create în programele Java. Vom zăbovi aici un pic.

Toate componentele grafice din Java sunt împărțite în două categorii: ușoare și grele. Marea majoritate a componentelor grafice (butoane, liste, arbori, etichete, tabele etc.) sunt ușoare. Aceasta înseamnă că sistemul de operare nu știe absolut nimic despre ele și nici măcar nu „bănuiește” existența lor. Componentele ușoare aparțin ferestrelor (ca cea pe care am afișat-o în lecția anterioară) și sunt afișate în acele ferestre.

Dacă vrem să afișăm un buton în fereastră, atunci trebuie doar să-l definim cu un cod ca următorul

JButton buttonPressMe = new JButton ("Apăsați-mă");

și plasați-l în locația specificată a ferestrei (detaliile relevante vor fi descrise mai târziu). Un buton este un obiect ușor și sistemul de operare nu are informații despre buton (pentru sistemul de operare butonul nu există deloc). Numai fereastra în care se află „știe” despre buton. Fereastra desenează butonul, interceptează evenimentele care au loc cu butonul, redesenează butonul dacă a fost ascuns de ceva etc. Dar fereastra în sine, ca atare, este ceva de care sistemul de operare este conștient, tocmai pentru că fereastra este o componentă grea. Doar fereastra are acces la resursele sistemului de operare (în special, resursele grafice).

Uită-te la codul sursă. Când am calculat coordonatele colțului din stânga sus al ferestrei înainte de a o afișa pe ecran, trebuia să cunoaștem rezoluția ecranului

Dimensiunea sSize = Toolkit.getDefaultToolkit().getScreenSize()

Ce poate oferi astfel de informații? Sistemul de operare și doar atât! Apoi, am folosit codul

încercați (UIManager.setLookAndFeel

(UIManager.getSystemLookAndFeelClassName());

prinde (Excepție lfe) ()

pentru a se asigura că aspectul ferestrei corespunde standardului adoptat într-un anumit sistem de operare. Ce poate oferi astfel de informații? Din nou - sistemul de operare! Deci, pentru a crea interfețe grafice, nu ne putem lipsi de pachetul java.awt.*.

Când o fereastră este afișată pe ecran, sistemul de operare alocă ferestrei resursele necesare (în primul rând memorie) și fereastra devine vizibilă. Apoi intră în joc componentele ușoare și toate lucrările ulterioare sunt efectuate aproape exclusiv cu ele.

Al doilea pachet importat (începând cu javax.swing) este responsabil pentru crearea de interfețe grafice ușoare (există și alte pachete, dar acesta este cel mai important și aproape întotdeauna folosit). Vom studia și stăpânim acest pachet treptat, pentru că... este destul de mare și destul de complex. Vom începe să facem acest lucru în lecția următoare, dar deocamdată să ne uităm la următoarea linie de cod sursă:

Clasa publică MoneyForNothing extinde JFrame (

Două elemente care sunt noi aici sunt cuvântul cheie extins și cuvântul JFrame.

Cuvântul cheie extinde (care înseamnă „a extinde”, dar este similar în sensul „moștenește” sau „a împrumuta proprietăți și comportament”) exprimă conceptul fundamental de programare orientată pe obiecte (sau, mai simplu, programare bazată pe clasă). Acest concept se numește „moștenire”. Acest lucru trebuie tratat temeinic.

Amintiți-vă, într-una dintre primele lecții () am discutat despre conceptul de cursuri și am folosit un motor de mașină ca exemplu. Cu toată varietatea de motoare și designul lor (vorbim, desigur, despre motoarele cu ardere internă), aproape toate aceste motoare sunt similare între ele: fiecare dintre ele are cilindri, pistoane, arbori cotiți, supape etc.

Desigur, un motor diesel uriaș pentru o cisternă nu poate fi comparat cu un motor minuscul cu alcool pentru un model de aeronavă, dar ei (ca să spunem așa) sunt, deși îndepărtați, rude. Au un strămoș comun - un motor abstract, iar motoarele în sine sunt descendenții lui (chiar dacă foarte, foarte îndepărtați).

În programare, un astfel de strămoș este de obicei numit „părinte” sau „superclasă”, adică. o clasă din care provin alte clase. Numele superclasei apare imediat după extinde. Deci, tradus în limbaj obișnuit, fragmentul de cod de mai sus poate fi citit ca: „clasa... extinde clasa JFrame”, „clasa... moștenește clasa JFrame” sau „clasa... împrumută proprietățile și comportamentul clasei JFrame.” Clasa JFrame definește proprietățile de bază și comportamentul ferestrelor grafice „standard”. Clasa JFrame în sine este localizată în pachetul javax.swing.* și acesta este pe care l-am importat la începutul programului.

JFrame este părintele (în terminologia Java, o superclasă) ferestrelor grafice (există și alte ferestre, de exemplu, ferestre de dialog, dar despre ele vom vorbi în timp util). Dacă te uiți la documentația Java, vei descoperi că clasa JFrame are mai mulți constructori, câmpuri și aproximativ două duzini de metode care definesc comportamentul unei anumite ferestre „standard”. Astfel, clasa noastră numită MoneyForNothing este un moștenitor al clasei JFrame (de obicei nu vorbim despre moștenitori, ci despre descendenți sau clase copii).

Vă rugăm să rețineți că clasa JFrame în sine este un descendent al mai multor clase (dintre care majoritatea aparțin pachetului deja familiar java.awt.*):

Pentru a nu reveni la această problemă, vă atragem atenția asupra faptului că în fruntea ierarhiei de moștenire Java se află clasele din pachetul java.lang.*. Acesta este singurul pachet din JDK care nu trebuie importat în mod explicit - este întotdeauna importat automat. Judecând după această „scără”, clasa JFrame este stră-stră-stră-nepotul java.lang.Object (imaginea de mai sus este numită științific ierarhia de clasă).

Toate componentele interfeței grafice cu utilizatorul (abreviat GUI, de la Graphical User Interface), care, rețineți, sunt elemente ușoare, trebuie plasate în interiorul ferestrei principale - succesorul JFrame-ului. Nu avem componente în acest moment, dar vor apărea în curând - promitem.

Acum să aruncăm o privire finală la codul nostru sursă, care arată astfel:

// Constructor

Bani publici pentru nimic() (

setTitle(„Bine ați venit la Money for Nothing”);

setSize(new Dimension(600, 400));

Dimensiunea sSize = Toolkit.getDefaultToolkit().getScreenSize(),

fSize = getSize();

if (fSize.height > sSize.height) (fSize.height = sSize.height;)

if (fSize.width > sSize.width) (fSize.width = sSize.width;)

setLocation((sSize.width - fSize.width)/2,

(sSize.height - fSize.height)/2);

setDefaultCloseOperation(EXIT_ON_CLOSE);

setVisible(true);

În primul rând, setăm titlul ferestrei (metoda setTitle("...")). Apoi se stabilesc dimensiunile orizontale și verticale ale ferestrei (metoda setSize(...)). După determinarea rezoluției ecranului monitorului, se calculează coordonatele colțului din stânga sus al ferestrei noastre și se afișează fereastra (metoda setLocation (...)) în locația specificată pe ecran.

După aceasta, determinăm ce trebuie făcut atunci când închidem o fereastră din meniul de sistem; în acest caz, este clar că aplicația trebuie să își încheie activitatea (EXIT_ON_CLOSE). Această linie scurtă și simplă ascunde de fapt o lume surprinzător de interesantă și intrigantă a procesării evenimentelor. Să spunem imediat: înțelegerea mecanismului de procesare a evenimentelor în Java este un punct cheie în dezvoltarea aplicațiilor grafice, iar începând de la următoarea lecție vom face exact asta.

În cele din urmă, ultima linie (metoda setVisible(true)) face fereastra vizibilă.

Desigur, nu am omis unele detalii, dar scopul nostru nu este să spunem totul în detaliu despre toate - există documentație, cărți de referință și manuale pentru asta. Scopul nostru este să oferim o direcție generală, un punct de plecare, pornind de la care dumneavoastră (dacă doriți și aveți suficientă persistență) să vă dezvoltați programele în direcțiile potrivite și să le completați cu funcționalitatea necesară.

Aceasta încheie lecția noastră. Cel mai important lucru pe care ar trebui să-l iei este conceptul de moștenire (împrumut). Acesta este cu adevărat un concept fundamental. Fără el, este imposibil să creați vreun program complex sau util în Java, așa că nu vă grăbiți să treceți mai departe, ci încă o dată revizuiți cu atenție și gândiți-vă la tot ce am învățat până acum.

Succes și ne vedem curând!

  • Serghei Savenkov

    un fel de recenzie „scurtă”... de parcă s-ar grăbi undeva