Uvod u JavaFx

1. Uvod

JavaFX je knjižnica za izgradnju bogatih klijentskih aplikacija s Javom. Pruža API za dizajniranje GUI aplikacija koji se izvode na gotovo svim uređajima s podrškom za Java.

U ovom uputstvu usredotočit ćemo se na nekoliko ključnih mogućnosti i funkcionalnosti.

2. JavaFX API

U Java 8, 9 i 10 nije potrebno dodatno postavljanje za početak rada s JavaFX knjižnicom. Projekt će biti uklonjen iz JDK počevši od JDK 11.

2.1. Arhitektura

JavaFX koristi hardverski ubrzani grafički cjevovod za prikazivanje, poznat kao Prizma. Štoviše, za potpuno ubrzavanje upotrebe grafike internim korištenjem koristi se softverski ili hardverski mehanizam za prikazivanje DirectX i OpenGL.

JavaFX ovisi o platformi Staklo sloj prozora s alatima za povezivanje s matičnim operativnim sustavom. Koristi red događaja operativnog sustava za planiranje upotrebe niti. Također, asinkrono obrađuje prozore, događaje, tajmere.

The Mediji i mreža motori omogućuju reprodukciju medija i podršku za HTML / CSS.

Pogledajmo kako izgleda glavna struktura JavaFX aplikacije:

Ovdje primjećujemo dva glavna spremnika:

  • Scena je glavni spremnik i ulazna točka aplikacije. Predstavlja glavni prozor i prosljeđuje se kao argument početak() metoda.
  • Scena je spremnik za držanje UI elemenata, kao što su Prikazi slike, Gumbi, Rešetke, Kutije teksta.

The Scena može se zamijeniti ili prebaciti na drugu Scena. Ovo predstavlja grafikon hijerarhijskih objekata, koji je poznat kao Scena Grafikon. Svaki element u toj hijerarhiji naziva se čvor. Pojedinačni čvor ima svoj ID, stil, efekte, rukovatelje događajima, stanje.

Uz to, Scena također sadrži spremnike izgleda, slike i medije.

2.2. Niti

Na razini sustava, JVM stvara zasebne niti za pokretanje i prikazivanje aplikacije:

  • Prizma nit prikazivanja - odgovorna za prikazivanje Grafikon scene odvojeno.
  • Nit aplikacije - glavna je nit bilo kojeg JavaFX programa. Svi aktivni čvorovi i komponente priključeni su na ovu nit.

2.3. Životni ciklus

The javafx.application.Application razred ima sljedeće metode životnog ciklusa:

  • u tome() - poziva se nakon izrade instance aplikacije. U ovom trenutku JavaFX API još nije spreman, tako da ovdje ne možemo stvoriti grafičke komponente.
  • start (faza pozornice) - ovdje su stvorene sve grafičke komponente. Također, glavna nit za grafičke aktivnosti započinje ovdje.
  • Stop() - poziva se prije isključivanja aplikacije; na primjer, kada korisnik zatvori glavni prozor. Korisno je nadvladati ovu metodu za neko čišćenje prije ukidanja aplikacije.

Statički pokretanje () metoda pokreće program JavaFX.

2.4. FXML

JavaFX koristi poseban jezik označavanja FXML za stvaranje sučelja prikaza.

Ovo pruža strukturu koja se temelji na XML-u za odvajanje pogleda od poslovne logike. XML je ovdje prikladniji jer može sasvim prirodno predstavljati Grafikon scene hijerarhija.

Napokon, za učitavanje .fxml datoteku, koristimo FXMLLoader klase, što rezultira objektnim grafom hijerarhije scene.

3. Početak rada

Da biste postali praktični i izradimo malu aplikaciju koja omogućuje pretraživanje popisa ljudi.

Prvo, dodajte a Osoba klasa modela - za predstavljanje naše domene:

javna klasa Person {private SimpleIntegerProperty id; privatno ime SimpleStringProperty; private SimpleBooleanProperty isEposed; // geteri, postavljači}

Primijetite kako, zamotati int, String i boolean vrijednosti, koristimo SimpleIntegerProperty, SimpleStringProperty, SimpleBooleanProperty razredi u javafx.beans.property paket.

Dalje, kreirajmo Glavni klasa koja proširuje Primjena sažetak klase:

javna klasa Main proširuje Program {@Override javni void start (Stage PrimaryStage) baca izuzetak {FXMLLoader loader = new FXMLLoader (Main.class.getResource ("/ SearchController.fxml")); Stranica AnchorPane = (AnchorPane) loader.load (); Scena scene = nova scena (stranica); primaryStage.setTitle ("Naslov ide ovdje"); primaryStage.setScene (scena); primaryStage.show (); } public static void main (String [] args) {pokretanje (args); }}

Naša glavna klasa nadjačava početak() metoda, koja je ulazna točka za program.

Onda FXMLLoader učitava hijerarhiju grafa objekta iz SearchController.fxml u AnchorPane.

Nakon pokretanja novog Scena, postavili smo ga na primarni Scena. Također smo postavili naslov za naš prozor i pokazati() to.

Imajte na umu da je korisno uključiti glavni() metoda za pokretanje JAR datoteke bez datoteke Pokretač JavaFX.

3.1. FXML prikaz

Zaronimo sada dublje u SearchController XML datoteka.

Za našu aplikaciju za pretraživanje dodati ćemo tekstualno polje za unos ključne riječi i gumba za pretraživanje:

AnchorPane je korijenski spremnik ovdje i prvi čvor hijerarhije grafa. Tijekom promjene veličine prozora, dijete će premjestiti dijete na točku sidrišta. The fx: kontroler atribut povezuje klasu Java s oznakom.

Dostupni su još neki ugrađeni izgledi:

  • BorderPane - dijeli raspored na pet odjeljaka: gornji, desni, donji, lijevi, središnji
  • HBox - rasporedite dječje komponente u vodoravnu ploču
  • VBox - podređeni čvorovi raspoređeni su u okomitom stupcu
  • GridPane - korisno za stvaranje mreže s redovima i stupcima

U našem primjeru, unutar vodoravne HBox ploča, koristili smo a Označiti postaviti tekst, Polje za tekst za ulaz i a Dugme. S fx: id označavamo elemente kako bismo ih kasnije mogli koristiti u Java kodu.

The VBox ploča je mjesto na kojem ćemo prikazati rezultate pretraživanja.

Zatim, za mapiranje na Java polja - koristimo @FXML napomena:

javna klasa SearchController {@FXML private TextField searchField; @FXML private Button searchButton; @FXML privatni VBox dataContainer; @FXML private TableView tableView; @FXML private void initialize () {// ploča za pretraživanje searchButton.setText ("Search"); searchButton.setOnAction (događaj -> loadData ()); searchButton.setStyle ("- fx-background-color: # 457ecd; -fx-text-fill: #ffffff;"); initTable (); }}

Nakon popunjavanja @FXML označena polja, inicijalizirati () pozvat će se automatski. Ovdje možemo izvesti daljnje radnje nad komponentama korisničkog sučelja - poput registracije slušatelja događaja, dodavanja stila ili promjene svojstva teksta.

U initTable () metodom stvorit ćemo tablicu koja će sadržavati rezultate, s 3 stupca, i dodati je u dataContainer VBox:

privatna praznina initTable () {tableView = novi TableView (); TableColumn id = novi TableColumn ("ID"); Naziv stupca tablice = novi stupac tablice ("IME"); Upotrijebljen je stupac tablice = novi stup stupca ("ZAPOSLEN"); tableView.getColumns (). addAll (id, ime, zaposlen); dataContainer.getChildren (). add (tableView); }

Napokon, sva ova ovdje opisana logika proizvest će sljedeći prozor:

4. API za vezanje

Sad kad se rješavaju vizualni aspekti, krenimo s proučavanjem podataka vezanja.

API za vezanje pruža neka sučelja koja obavještavaju objekte kada dođe do promjene vrijednosti drugog objekta.

Vrijednost možemo povezati pomoću vezati() metodom ili dodavanjem slušatelja.

Jednosmjerno vezanje pruža vezanje samo za jedan smjer:

searchLabel.textProperty (). bind (searchField.textProperty ());

Ovdje će svaka promjena u polju za pretraživanje ažurirati tekstualnu vrijednost naljepnice.

Za usporedbu, dvosmjerno vezivanje sinkronizira vrijednosti dva svojstva u oba smjera.

Alternativni način vezivanja polja su Slušatelji promjena:

searchField.textProperty (). addListener ((uočljivo, staraVrijednost, novaVrijednost) -> {searchLabel.setText (novaValue);});

The Uočljiv sučelje omogućuje promatranje vrijednosti objekta za promjene.

Kao primjer toga, najčešće korištena provedba je javafx.collections.ObservableList sučelje:

ObservableList masterData = FXCollections.observableArrayList (); Rezultati ObservableList = FXCollections.observableList (masterData);

Ovdje će svaka promjena modela, poput umetanja, ažuriranja ili uklanjanja elemenata, odmah obavijestiti kontrole korisničkog sučelja.

The masterData Popis će sadržavati početni popis Osoba objekata, a popis rezultata bit će popis koji ćemo prikazati nakon pretraživanja.

Također moramo ažurirati initTable () metodu za povezivanje podataka u tablici na početni popis i povezivanje svakog stupca s Osoba polja razreda:

private void initTable () {tableView = novi TableView (FXCollections.observableList (masterData)); TableColumn id = novi TableColumn ("ID"); id.setCellValueFactory (novi PropertyValueFactory ("id")); Naziv stupca tablice = novi stupac tablice ("IME"); name.setCellValueFactory (novi PropertyValueFactory ("ime")); Upotrijebljen je stupac tablice = novi stup stupca ("ZAPOSLEN"); zaposlen.setCellValueFactory (novi PropertyValueFactory ("isEcreded")); tableView.getColumns (). addAll (id, ime, zaposlen); dataContainer.getChildren (). add (tableView); }

5. Istodobnost

Rad s komponentama korisničkog sučelja u grafikonu scene nije siguran u nit, jer mu se pristupa samo iz niti aplikacije. The javafx.koncurrent paket je tu da pomogne u multithreadingu.

Pogledajmo kako možemo izvršiti pretraživanje podataka u pozadini niti:

private void loadData () {String searchText = searchField.getText (); Zadatak zadatak = novi Zadatak() {@Override zaštićeni poziv ObservableList () baca iznimku {updateMessage ("Učitavanje podataka"); vratiti FXCollections.observableArrayList (masterData .stream () .filter (vrijednost -> value.getName (). toLowerCase (). sadrži (searchText)) .collect (Collectors.toList ())); }}; }

Ovdje stvaramo jednokratni zadatak javafx.concurrent.Task objekt i nadjačati poziv() metoda.

The poziv() metoda u potpunosti se izvodi na pozadinskoj niti i vraća rezultat u nit aplikacije. To znači da će svaka manipulacija komponentama korisničkog sučelja unutar ove metode izuzeti runtime.

Međutim, updateProgress (), updateMessage () može se pozvati radi ažuriranja stavki niti aplikacije. Kada stanje zadatka prijeđe u USPJEŠENO stanje, onSucceeded () obrađivač događaja poziva se iz niti aplikacije:

task.setOnSucceeded (događaj -> {rezultati = task.getValue (); tableView.setItems (FXCollections.observableList (rezultati));}); 

U istom povratnom pozivu ažurirali smo tableView podaci na novi popis rezultata.

The Zadatak je Izvodljivo, pa da bismo ga pokrenuli trebamo samo pokrenuti novi Nit s zadatak parametar:

Tema th = nova nit (zadatak); th.setDaemon (istina); th.start ();

The setDaemon (true) zastava označava da će nit završiti nakon završetka posla.

6. Rukovanje događajima

Događaj možemo opisati kao radnju koja bi aplikaciji mogla biti zanimljiva.

Na primjer, korisničke radnje poput klikova mišem, pritiska tipki, promjene veličine prozora obrađuju se ili ih obaviještava javafx.event.Događaj klase ili bilo koje od njegovih potklasa.

Također, razlikujemo tri vrste događaja:

  • InputEvent - sve vrste radnji tipki i miša poput KEY_PRESSED, KEY_TYPED, KEY_RELEASED ili PRITISCI MIŠA, OTPUSTILI MIŠA
  • ActionEvent - predstavlja razne radnje poput ispaljivanja a Dugme ili dorada a KeyFrame
  • WindowEventWINDOW_SHOWING, WINDOW_SHOWN

Demonstrirati, donji fragment koda hvata slučaj pritiska na Unesi tipka preko searchField:

searchField.setOnKeyPress (događaj -> {ako (event.getCode (). je jednako (KeyCode.ENTER)) {loadData ();}});

7. Stil

UI JavaFX aplikacije možemo promijeniti primjenom prilagođenog dizajna.

Prema zadanim postavkama JavaFX koristi modena.css kao CSS resurs za cijelu aplikaciju. Ovo je dio jfxrt.jar.

Da bismo nadjačali zadani stil, sceni možemo dodati tablicu stilova:

scene.getStylesheets (). add ("/ search.css");

Također se možemo poslužiti ugrađenim stilom; na primjer, za postavljanje svojstva stila za određeni čvor:

searchButton.setStyle ("- fx-background-color: slateblue; -fx-text-fill: white;");

8. Zaključak

Ovaj kratki opis obuhvaća osnove JavaFX API-ja. Prošli smo kroz unutarnju strukturu i predstavili ključne mogućnosti njegove arhitekture, životnog ciklusa i komponenata.

Kao rezultat toga, naučili smo i sada smo u mogućnosti stvoriti jednostavnu GUI aplikaciju.

Kao i uvijek, puni izvorni kod udžbenika dostupan je na GitHub-u.