APLICAȚII JAVA FXML CU BAZE DE DATE Breviar teoretic În industrie trendul aplicațiilor grafice cu interfața definită printr-o variantă a limbajului XML (Extensible Markup Language) este în continuă creștere. Pentru a satisface aceste cerințe Microsoft au inventat XAML, Flex – MXML, iar acum și Oracle are o variantă proprietară numită Java FXML. Java FXML este un limbaj bazat pe XML folosit la construirea de grafuri de obiecte Java. Este o alternativă la construirea acestor grafuri prin metode de cod procedural și este ideal pentru definirea de interfețe cu utilizatorul, deoarece structura unui document XML este foarte asemănătoare cu structura de cod folosită la definirea unui graf de scenă într-o aplicație Java FX obișnuită. FXML nu are o schemă, dar are o structură predefinită. Ceea ce poate fi exprimat în FXML și cum este aplicat grafului scenei depinde de interfața de cod a obiectelor construite. Deoarece FXML este mapat direct în cod Java, aproape toate clasele de Java FX au un element XML corespondent cu atributele descrise în clasa Java mapată. Java FX BorderPane border = new BorderPane(); Label topPaneText = new Label("Page Title"); border.setTop(topPaneText); Label centerPaneText = new Label ("Some data here"); border.setCenter(centerPaneText); Java FXML <BorderPane> <top>
27
Embed
Aplicații JAVA FXML CU BAZE DE DATErobotics.ucv.ro/carti/java/Laborator/Aplicatii Java FXML... · Web viewAplicații JAVA FXML CU BAZE DE DATE Breviar teoretic În industrie trendul
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
APLICAȚII JAVA FXML CU BAZE DE DATE
Breviar teoreticÎn industrie trendul aplicațiilor grafice cu interfața definită printr-o variantă a limbajului XML (Extensible Markup Language) este în continuă creștere. Pentru a satisface aceste cerințe Microsoft au inventat XAML, Flex – MXML, iar acum și Oracle are o variantă proprietară numită Java FXML.
Java FXML este un limbaj bazat pe XML folosit la construirea de grafuri de obiecte Java. Este o alternativă la construirea acestor grafuri prin metode de cod procedural și este ideal pentru definirea de interfețe cu utilizatorul, deoarece structura unui document XML este foarte asemănătoare cu structura de cod folosită la definirea unui graf de scenă într-o aplicație Java FX obișnuită.
FXML nu are o schemă, dar are o structură predefinită. Ceea ce poate fi exprimat în FXML și cum este aplicat grafului scenei depinde de interfața de cod a obiectelor construite. Deoarece FXML este mapat direct în cod Java, aproape toate clasele de Java FX au un element XML corespondent cu atributele descrise în clasa Java mapată.
Java FX
BorderPane border = new BorderPane();
Label topPaneText = new Label("Page Title");
border.setTop(topPaneText);
Label centerPaneText = new Label ("Some data here");
border.setCenter(centerPaneText);
Java FXML
<BorderPane>
<top>
<Label text="Page Title"/>
</top>
<center>
<Label text="Some data here"/>
</center>
</BorderPane>
Pentru a eficientiza procesul de dezvoltare al aplicațiilor cu interfețe grafice au fost create șabloane (patternuri) și arhitecturi de aplicații. Cel mai popular pattern pentru aplicațiile desktop este Model View Controller, care a devenit folosit chiar și în aplicațiile web.
Patternul Model View Controller este o metodă de a implementa interfețe cu utilizatorul, care divide software-ul implementat în trei părți interconectate, pentru a separa reprezentările interne de informațiile prezentate utilizatorilor.
Din perspectiva patternului Model View Controller, fișierul care conține descrierea XML a interfeței este View-ul. Controllerul este o clasă de Java care este declarată ca și controllerul fișierului XML. Modelul este constituit din obiectele domeniului definite în Java. Modelul se leagă de interfață folosind Controllere.
Pentru a interacționa cu o bază de date vom încapsula logica necesară interogărilor și extragerii primare de date folosind un alt pattern numit Data Access Object. Această abstractizare permite operațiuni specifice (de exemplu operațiile CRUD) fără a divulga detaliile mecanismului de persistență a datelor.
Aceste două patternuri ne vor ajuta să ne structurăm aplicația într-o manieră scalabilă și ușor de înțeles.
Model Punctul central al aplicației: datele și regulile procesului. Este independent de interfață.
View Afișează datele din model. Are și rolul de a transmite evenimente legate de interacțiunea utilizatorului la Controller.
Controller Conectează modelul si view-ul (interfața cu utilizatorul). Are rolul de a pregăti datele pentru afișare și de a răspunde la comenzile primite din interfață.
Aplicație Realizarea unei aplicații grafice folosind Java FXML și conectarea acesteia la o bază de date SQLite
Aplicația pe care o vom dezvolta se va conecta la o bază de date SQLite, care conține o tabelă Person (FirstName, LastName), și va pune la dispoziția utilizatorului o interfața prietenoasă prin care se poate realiza operațiile de CRUD (Create, Read, Update, Delete). Interfața va arăta în felul următor:
Vom folosi mediul de programare NetBeans și vom crea un nou proiect Java – Application cu numele SqliteJavaFxml. Pentru aplicația noastră avem nevoie de pachetul sqlite-jdbc, pe care îl putem downloada de la acest link sqlite-jdbc-3.8.11.2.jar .
După ce am descărcat sqlite-jdbc, trebuie adăugat la referințele proiectului in directorul Libraries – click dreapta → Add JAR/Folder → Alegem fișierul nou descărcat sqlite-jdbc-3.8.11.2.jar.
Următorii pași care sunt sugerați în dezvoltarea acestei aplicații sunt stabilirea structurii de fișiere. Ne vom crea module (packages) astfel încât să urmăm principiile MVC și DAO.
Vom redenumi packageul implicit sqlite.java.fxml în model pentru a respecta convenția noastră.
Apoi vom crea și următoarele module view și dataaccess. Restul fișierelor vor fi adăugate în modulele aferente folosind meniul contextual click dreapta pe modul și Add Other…
Structura finală a proiectului va fi cea din figura alăturată:
Vom porni de la stabilirea clară a modelului aplicației, adică fișierul Person.java, urmat de layerul de acces la baza de date (PersonDAO – Data Access Object), clasa principală a aplicației noastre (SqliteJavaFxml.java) care face legatura dintre toate componentele, la urmă rămânând fișierele care descriu interfața și controllerele asociate acestora.
Fișierul Person.java conține definiția clasei Person, care va corespunde ca și proprietăți tabelei Person din baza de date folosită în aplicație.
public Person(int id, String firstName, String lastName) {
this.id = id;
this.firstName = new SimpleStringProperty(firstName);
this.lastName = new SimpleStringProperty(lastName);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public StringProperty firstNameProperty() {
return firstName;
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
public StringProperty lastNameProperty() {
return lastName;
}
}
După definirea proprietăților, vom putea scrie mai departe modulul de acces la baza de date. Acest modul se va ocupa de crearea tabelei în cazul în care nu există deja și de interacționarea din cod Java cu tabela Person (Create, Read, Update, Delete). Conținutul fișierului PersonDAO va fi următorul:
package dataaccess;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import model.SqliteJavaFxml;
import model.Person;
public class PersonDAO {
private final String databaseConnectionString;
public PersonDAO(String databaseConnectionString) throws ClassNotFoundException {
Fișierul principal al aplicației noastre îl constituie SqliteJavaFxml.java și va conține codul pentru gestionarea scenei și a viewurilor. În acest fișier vom scrie următoarele:
package model;
import dataaccess.PersonDAO;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import view.PersonEditDialogController;
import view.PersonOverviewController;
public class SqliteJavaFxml extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
private final PersonDAO personDAO;
public SqliteJavaFxml() throws ClassNotFoundException {
this.personDAO = new PersonDAO("jdbc:sqlite:crudapp.db");
Observăm că în constructorul clasei principale se află instanțierea Data Access Objectului pentru persoane care primește ca parametru adresa bazei de date SQLite. Reamintim că această baze de date se creează automat la rularea programului direct în directorul proiectului.
this.personDAO = new PersonDAO("jdbc:sqlite:crudapp.db");
Metodele care controlează viewurile sunt initRootLayout, showPersonOverview, showPersonEditDialog.
După cum se poate observa, toate cele trei metode au o structura similară, în sensul că se deschid cu un bloc de gestionare a excepțiilor provenite din lipsa fișierelor (Input/Output) sau lipsa accesului la aceste resurse. Resursele, adică fișierele în care sunt descrise viewurile sunt încărcate cu ajutorul clasei FXMLLoader, folosind metodele
setLocation si load.
Pentru a lega controllerele de aceste viewuri, apelăm tot la loaderul FXML, folosind metoda getController.
Vom continua cu definirea fiecărui View și Controller asociat.
Fișierul RootLayout.fxml va conține doar un cadru pentru aplicația noastră, va fi practic containerul care dimensionează fereastra principală a aplicației.
Acest View nu are nevoie de un controller asociat deoarece nu are legături de date, el fiind folosit doar pentru a aranja layoutul aplicației.
Fișierul PersonOverview.fxml va conține descrierea tabelului FXML corespunzător tabelei Person dintr-o bază de date SQLite, care va fi folosit desigur la extragerea și afișarea datelor din acea tabelă. În acest View vom regăsi și trei butoane de acțiune care au rolul de a manipula datele din tabel, respectiv baza de date, prin intermediul de ferestre intermediare sau acțiuni asupra modelului.
De remarcat sunt legarea proprietăților din controller la view cu atributul fx:id (fx:id="firstNameColumn") și
legarea funcțiilor cu prefixul "#" (#handleNewPerson);
Controllerul acestui View se regăsește în fișierul PersonOverviewController.java și va face legătura dintre interfața grafica și model, persistând rezultatul acțiunilor utilizatorului în baza de date prin intermediul Person Data Access Objectului.
De remarcat sunt decoratorii (@FXML) folosiți pentru a marca proprietățile și funcțiile ce interacționează în corpul lor
cu elemente din fișierul FXML pe care îl controlează. Dacă metodele, respectiv proprietățile nu sunt decorate cu @FXML, aplicația va avea erori de funcționare. În cazul în care nu este selectată nicio înregistrare din tabel, apăsarea
butoanelor de acțiune pentru editare și ștergere vor declanșa apariția unui mesaj de eroare (metoda showAlert).
alert.setContentText("Please select a person in the table.");
alert.showAndWait();
}
}
Ultimul view folosit în aplicație este cel care descrie fereastra de tip dialog prin care un utilizator poate introduce datele unei persoane noi sau poate edita pe cele ale uneia existente în baza de date. În funcție de metoda de unde a fost apelat controllerul acestui view, rezultatul acțiunii de a apăsa butonul OK va declanșa o acțiune de adăugare sau de editare a tabelei Person.
Controllerul pentru acest view, PersonEditDialogController.java , este folosit pentru a verifica introducerea corectă de date și validarea modificarărilor la nivel de interfață. Acesta comunică schimbările modelului controllerului PersonOverviewController, iar acesta din urmă va acționa și în baza de date.
package view;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import model.Person;
public class PersonEditDialogController {
@FXML
private TextField firstNameField;
@FXML
private TextField lastNameField;
private Stage dialogStage;
private Person person;
private boolean okClicked = false;
@FXML
private void initialize() {
}
public void setDialogStage(Stage dialogStage) {
this.dialogStage = dialogStage;
}
public void setPerson(Person person) {
this.person = person;
firstNameField.setText(person.getFirstName());
lastNameField.setText(person.getLastName());
}
public boolean isOkClicked() {
return okClicked;
}
@FXML
private void handleOk() {
if (isInputValid()) {
person.setFirstName(firstNameField.getText());
person.setLastName(lastNameField.getText());
okClicked = true;
dialogStage.close();
}
}
@FXML
private void handleCancel() {
dialogStage.close();
}
private boolean isInputValid() {
String errorMessage = "";
if (firstNameField.getText() == null || firstNameField.getText().length() == 0) {
errorMessage += "No valid first name!\n";
}
if (lastNameField.getText() == null || lastNameField.getText().length() == 0) {
Putem vedea relația dintre aceste doua controllere ca Master-Slave, unul fiind utilizat pentru controlul la nivel doar de interfață (PersonEditDialogController), iar celălalt pentru a gestiona logica aplicației.
Așadar, am realizat o aplicație cu interfață grafică, susținută de o bază de date SQLite. Concluzia este că aplicând o arhitectură MVC putem scrie codul într-un mod modular, ușor de extins, care ține cont de patternuri aplicate în tehnicile moderne de programare și putem îl refolosi pentru aplicații asemănătoare.