Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
laboratoare:laborator09 [2015/12/18 00:11]
Andrei Roșu-Cojocaru
laboratoare:laborator09 [2015/12/28 15:52] (current)
Andrei Roșu-Cojocaru
Line 7: Line 7:
   * identificarea principalelor componente din cadrul arhitecturii JavaFX;   * identificarea principalelor componente din cadrul arhitecturii JavaFX;
   * descrierea structurii generale a unei aplicații JavaFX și a firelor de execuție din contextul cărora pot fi accesate obiectele corespunzătoare controalelor grafice, respectiv interacțiunii cu utilizatorul;​   * descrierea structurii generale a unei aplicații JavaFX și a firelor de execuție din contextul cărora pot fi accesate obiectele corespunzătoare controalelor grafice, respectiv interacțiunii cu utilizatorul;​
-  * implementarea unei interfețe cu utilizatorul folosind Scene Builder ​2.0 / FXML cu injectarea controalelor grafice / metodelor de tratare a evenimentelor în clasa controller din codul sursă;+  * implementarea unei interfețe cu utilizatorul folosind Scene Builder / FXML cu injectarea controalelor grafice / metodelor de tratare a evenimentelor în clasa controller din codul sursă;
   * înțelegerea mecanismului de tratare a evenimentelor legate de interacțiunea cu utilizatorul în JavaFX; dezvoltarea de filtre și metode de tratare pentru diferite acțiuni ale utilizatorului;​   * înțelegerea mecanismului de tratare a evenimentelor legate de interacțiunea cu utilizatorul în JavaFX; dezvoltarea de filtre și metode de tratare pentru diferite acțiuni ale utilizatorului;​
   * însușirea practicilor utilizate pentru dezvoltarea aplicațiilor JavaFX.   * însușirea practicilor utilizate pentru dezvoltarea aplicațiilor JavaFX.
Line 28: Line 28:
   * **integrare cu Java**. JavaFX ​ este o interfaţă de programare integrată în distribuţia limbajului de programare Java, instalarea sa făcându-se împreună cu acesta; prin urmare, din JavaFX pot fi accesate toate API-urile Java cu funcţionalităţile lor, acesta reprezentând o alternativă la celelalte limbaje de programare care folosesc Java Virtual Machine, precum JRuby sau Scala; ​   * **integrare cu Java**. JavaFX ​ este o interfaţă de programare integrată în distribuţia limbajului de programare Java, instalarea sa făcându-se împreună cu acesta; prin urmare, din JavaFX pot fi accesate toate API-urile Java cu funcţionalităţile lor, acesta reprezentând o alternativă la celelalte limbaje de programare care folosesc Java Virtual Machine, precum JRuby sau Scala; ​
   * **limbajul de adnotare FXML şi utilitarul SceneBuilder**. FXML este un limbaj declarativ de adnotare bazat pe XML prin intermediul căruia pot fi dezvoltate interfeţe grafice cu utilizatorul,​ fără a fi necesar ca aplicaţia să fie recompilată de fiecare dată când sunt modificate elemente din cadrul acesteia. În acest mod se realizează o separare între nivelul de prezentare și nivelul de logică a aplicației. SceneBuilder permite construirea interfeţei în mod vizual, generând automat şi documentul FXML asociat, acesta putând fi integrat apoi în orice mediu de dezvoltare. Astfel, nu mai este necesară decât implementarea mecanismelor de tratare a evenimentelor corespunzătoare diferitelor controale (elemente din cadrul interfeței grafice);   * **limbajul de adnotare FXML şi utilitarul SceneBuilder**. FXML este un limbaj declarativ de adnotare bazat pe XML prin intermediul căruia pot fi dezvoltate interfeţe grafice cu utilizatorul,​ fără a fi necesar ca aplicaţia să fie recompilată de fiecare dată când sunt modificate elemente din cadrul acesteia. În acest mod se realizează o separare între nivelul de prezentare și nivelul de logică a aplicației. SceneBuilder permite construirea interfeţei în mod vizual, generând automat şi documentul FXML asociat, acesta putând fi integrat apoi în orice mediu de dezvoltare. Astfel, nu mai este necesară decât implementarea mecanismelor de tratare a evenimentelor corespunzătoare diferitelor controale (elemente din cadrul interfeței grafice);
-  * **componente WebView**. Un modul ce foloseşte tehnologia WebKitHTML permite integrarea de pagini Internet în cadrul unei interfeţe grafice. De asemenea, codul JavaScript ce rulează în WebView poate accesa orice API-uri Java, la fel cum API-urile Java pot executa cod JavaScript care rulează în WebView. Există suport și pentru anumite funcționalități HTML5 (Web Sockets, Web Workers, Web Fonts) sau capabilități de tipărire;​ +  * **componente WebView**. Un modul ce foloseşte tehnologia WebKitHTML permite integrarea de pagini Internet în cadrul unei interfeţe grafice. De asemenea, codul JavaScript ce rulează în [[https://​docs.oracle.com/​javase/​8/​javafx/​api/​javafx/​scene/​web/​WebView.html|WebView]] poate accesa orice API-uri Java, la fel cum API-urile Java pot executa cod JavaScript care rulează în WebView. Există suport și pentru anumite funcționalități HTML5 (Web Sockets, Web Workers, Web Fonts) sau capabilități de tipărire;​ 
-  * **interoperabilitate cu tehnologia Swing**. Aplicaţiile Swing existente pot fi extinse cu funcţionalităţi JavaFX, ca redarea de conţinuturi grafice sau a unor pagini Internet integrate. Clasa ''​SwingNode'' ​permite integrarea unui conținut dezvoltat folosind tehnologia Swing în cadrul aplicației JavaFX; +  * **interoperabilitate cu tehnologia Swing**. Aplicaţiile Swing existente pot fi extinse cu funcţionalităţi JavaFX, ca redarea de conţinuturi grafice sau a unor pagini Internet integrate. Clasa [[https://​docs.oracle.com/​javase/​8/​javafx/​api/​javafx/​embed/​swing/​SwingNode.html|SwingNode]] permite integrarea unui conținut dezvoltat folosind tehnologia Swing în cadrul aplicației JavaFX; 
-  * **biblioteci de controale şi foi de stil**. JavaFX pune la dispoziţia programatorilor majoritatea controalelor necesare pentru dezvoltarea unei interfeţe cu utilizatorul complete (inclusiv ​''​DatePicker'' ​și ''​TreeTableView''​), aspectul acestora putând fi particularizat folosind tehnologii web standard ca foile de stil (//eng.// CSS – cascading style sheets), prin intermediul claselor ''​Styleable*'';​+  * **biblioteci de controale şi foi de stil**. JavaFX pune la dispoziţia programatorilor majoritatea controalelor necesare pentru dezvoltarea unei interfeţe cu utilizatorul complete (inclusiv ​[[https://​docs.oracle.com/​javase/​8/​javafx/​api/​javafx/​scene/​control/​DatePicker.html|DatePicker]] ​și [[https://​docs.oracle.com/​javase/​8/​javafx/​api/​javafx/​scene/​control/​TreeTableView.html|TreeTableView]]), aspectul acestora putând fi particularizat folosind tehnologii web standard ca foile de stil (//eng.// CSS – cascading style sheets), prin intermediul claselor ''​Styleable*'';​
   * **tema Modena** este folosită ca implicită pentru toate aplicațiile JavaFX (înlocuind tema Caspian, care poate fi utilizată prin apelul metodei ''​setUserAgentStylesheet(STYLESHEET_CASPIAN)''​ în metoda ''​start()''​ a clasei derivate din ''​Application'';​   * **tema Modena** este folosită ca implicită pentru toate aplicațiile JavaFX (înlocuind tema Caspian, care poate fi utilizată prin apelul metodei ''​setUserAgentStylesheet(STYLESHEET_CASPIAN)''​ în metoda ''​start()''​ a clasei derivate din ''​Application'';​
   * **funcționalități de grafică 3D**. Biblioteca de grafică 3D a fost îmbogățită prin:   * **funcționalități de grafică 3D**. Biblioteca de grafică 3D a fost îmbogățită prin:
Line 1993: Line 1993:
 ==== JavaFX Scene Builder ==== ==== JavaFX Scene Builder ====
  
-Documentele FXML pot fi dezvoltate în mod vizual folosind utilitarul [[http://www.oracle.com/technetwork/java/javase/​downloads/​sb2download-2177776.html|SceneBuilder]],​ disponibil pe platformele Windows (32/64 de biţi), Mac OS X şi Linux (32/64 biţi) – sub formă de pachete ''​.deb''​ şi arhive ''​tar.gz''​. ​+Documentele FXML pot fi dezvoltate în mod vizual folosind utilitarul [[http://gluonhq.com/open-source/scene-builder/​|SceneBuilder]],​ disponibil pe platformele Windows (32/64 de biţi), Mac OS X şi Linux (32/64 biţi) – sub formă de pachete ''​.deb''​ şi arhive ''​tar.gz''​. ​
  
 Acesta permite construirea interfeței grafice interactiv, simultan cu generarea automată a documentului FXML, fiecare control putând fi configurat, grupate în proprietăţi,​ moduri de dispunere şi cod. Acesta permite construirea interfeței grafice interactiv, simultan cu generarea automată a documentului FXML, fiecare control putând fi configurat, grupate în proprietăţi,​ moduri de dispunere şi cod.
Line 2177: Line 2177:
  
 În privinţa nivelului de logică a aplicaţiei,​ cele mai frecvent uzitate tehnici sunt:  În privinţa nivelului de logică a aplicaţiei,​ cele mai frecvent uzitate tehnici sunt: 
-  * folosirea ​ecrane animatelor ​care să indice progresul acelor procese de lungă durată astfel încât aplicaţia să nu pară că nu răspunde la interacţiunea cu utilizatorul;​+  * folosirea ​ecranelor animate ​care să indice progresul acelor procese de lungă durată astfel încât aplicaţia să nu pară că nu răspunde la interacţiunea cu utilizatorul;​
   * folosirea unor denumiri simbolice pentru pachetele implementate pentru ca aplicaţia să fie mai organizată şi mai uşor de întreţinut;​   * folosirea unor denumiri simbolice pentru pachetele implementate pentru ca aplicaţia să fie mai organizată şi mai uşor de întreţinut;​
   * implementarea arhitecturii model-view-controller (MVC) prin intermediul fişierelor FXML pentru definirea scenelor, acestea reprezentând partea de vizualizare,​ în timp ce modelul este reprezentat de obiectele de domeniu specifice aplicaţiei,​ iar partea de control aparţine codului Java care defineşte comportamentul interfeţei grafice în interacţiunea cu utilizatorul;​   * implementarea arhitecturii model-view-controller (MVC) prin intermediul fişierelor FXML pentru definirea scenelor, acestea reprezentând partea de vizualizare,​ în timp ce modelul este reprezentat de obiectele de domeniu specifice aplicaţiei,​ iar partea de control aparţine codului Java care defineşte comportamentul interfeţei grafice în interacţiunea cu utilizatorul;​
Line 2213: Line 2213:
  
 **2**. Să se acceseze fişierul ''​authentication.fxml''​ (localizat în directorul ''​src'',​ subdirectorul ''​resources/​fxml''​) folosind utilitarul SceneBuilder sau cu orice alt editor de text – inclusiv din cadrul mediilor integrate de dezvoltare Eclipse / Eclipse. Acesta conține un formular pentru autentificarea utilizatorilor. **2**. Să se acceseze fişierul ''​authentication.fxml''​ (localizat în directorul ''​src'',​ subdirectorul ''​resources/​fxml''​) folosind utilitarul SceneBuilder sau cu orice alt editor de text – inclusiv din cadrul mediilor integrate de dezvoltare Eclipse / Eclipse. Acesta conține un formular pentru autentificarea utilizatorilor.
 +
 +{{ :​laboratoare:​laborator09:​activitate_de_laborator01.png?​nolink }}
 +⇓
 +{{ :​laboratoare:​laborator09:​activitate_de_laborator02.png?​nolink }}
  
 **a)** Să se precizeze clasa controller pentru documentul FXML (având ca rădăcină un mecanism de gestiune a conținutului de tip ''​AnchorPane''​) ca fiind ''​ro.pub.cs.aipi.lab09.controller.Authentication''​. **a)** Să se precizeze clasa controller pentru documentul FXML (având ca rădăcină un mecanism de gestiune a conținutului de tip ''​AnchorPane''​) ca fiind ''​ro.pub.cs.aipi.lab09.controller.Authentication''​.
 +
 +{{ :​laboratoare:​laborator09:​activitate_de_laborator03.png?​nolink }}
 +
 +<file xml authentication.xml>​
 +<!-- different imports -->
 +
 +<​AnchorPane fx:​id="​AnchorPane"​ maxHeight="​-Infinity"​ maxWidth="​-Infinity"​ minHeight="​-Infinity"​ minWidth="​-Infinity" ​
 +prefHeight="​128.0"​ prefWidth="​336.0000999999975" ​
 +style="​-fx-background-color:​ beige;"​ xmlns="​http://​javafx.com/​javafx/​8"​ xmlns:​fx="​http://​javafx.com/​fxml/​1"​ fx:​controller="​ro.pub.cs.aipi.lab09.controller.Authentication">​
 +  ​
 +  <!-- description of the graphic user interface -->
 +  ​
 +</​AnchorPane>​
 +</​file>​
  
 **b)** Pentru butoanele ''​Ok''​ / ''​Cancel'',​ să se specifice metodele care vor fi executate în cazul producerii unui eveniment de tipul ''​ActionEvent.ACTION''​ (proprietatea ''​onAction()''​) ca fiind: **b)** Pentru butoanele ''​Ok''​ / ''​Cancel'',​ să se specifice metodele care vor fi executate în cazul producerii unui eveniment de tipul ''​ActionEvent.ACTION''​ (proprietatea ''​onAction()''​) ca fiind:
   * ''​okButtonHandler()'';​   * ''​okButtonHandler()'';​
-  * ''​cancelButtonHandler()''​;+  * ''​cancelButtonHandler()''​. 
 + 
 +{{ :​laboratoare:​laborator09:​activitate_de_laborator04a.png?​nolink }} ⇒ {{ :​laboratoare:​laborator09:​activitate_de_laborator04b.png?​nolink }} 
 + 
 +<file xml authentication.xml>​ 
 +<!-- ... --> 
 +<Button mnemonicParsing="​false"​ onAction="#​okButtonHandler"​ text="​OK"​ /> 
 +<!-- ... --> 
 +</​file>​
  
 **c)** Să se specifice identificatori (proprietatea ''​fx:​id''​) pentru: **c)** Să se specifice identificatori (proprietatea ''​fx:​id''​) pentru:
   * cele două câmpuri text pentru specificarea parametrilor nume utilizator / parolă, având denumirile ''​usernameTextField''​ / ''​passwordTextField'';​   * cele două câmpuri text pentru specificarea parametrilor nume utilizator / parolă, având denumirile ''​usernameTextField''​ / ''​passwordTextField'';​
   * eticheta în care se va afișa un mesaj de eroare în situația în care operația de autentificare eșuează, având denumirea ''​errorLabel''​.   * eticheta în care se va afișa un mesaj de eroare în situația în care operația de autentificare eșuează, având denumirea ''​errorLabel''​.
 +
 +{{ :​laboratoare:​laborator09:​activitate_de_laborator05a.png?​nolink }} ⇒ {{ :​laboratoare:​laborator09:​activitate_de_laborator05b.png?​nolink }}
 +
 +<file xml authentication.xml>​
 +<!-- ... -->
 +<​TextField fx:​id="​usernameTextField"​ prefWidth="​200.0"​ GridPane.columnIndex="​1"​ GridPane.rowIndex="​0"​ />
 +<!-- ... -->
 +</​file>​
  
 **d)** În clasa controller ''​ro.pub.cs.aipi.lab09.controller.Authentication'',​ sa se implementeze metodele ''​okButtonHandler()''​ / ''​cancelButtonHandler()''​ ce gestionează accesul utilizatorului în aplicaţie. Vor avea dreptul de a accesa sistemul informatic doar utilizatorii al căror tip este administrator. În cazul în care combinaţia (utilizator,​ parolă) este incorectă sau utilizatorul nu are acces în sistem, se va afişa un mesaj corespunzător care va rămâne pe ecran maxim 5 secunde. **d)** În clasa controller ''​ro.pub.cs.aipi.lab09.controller.Authentication'',​ sa se implementeze metodele ''​okButtonHandler()''​ / ''​cancelButtonHandler()''​ ce gestionează accesul utilizatorului în aplicaţie. Vor avea dreptul de a accesa sistemul informatic doar utilizatorii al căror tip este administrator. În cazul în care combinaţia (utilizator,​ parolă) este incorectă sau utilizatorul nu are acces în sistem, se va afişa un mesaj corespunzător care va rămâne pe ecran maxim 5 secunde.
Line 2264: Line 2298:
 </​spoiler>​ </​spoiler>​
  
-**3**. În clasa ''​TableManagement'',​ din pachetul ''​ro.pub.cs.aipi.lab09.controller''​ să se populeze obiectul ''​attributesGridPane''​ care va avea pe două coloane obiectele de tip ''​ArrayList<​Label>''​ (''​attributeLabels''​),​ respectiv ''​ArrayList<​Control>''​ (''​attributeControls''​).\\ Înainte de a adăuga obiectul propriu-zis,​ trebuie să îi specificaţi poziţia în cadrul obiectului de tip ''​GridPane'',​ prin intermediul metodei ​''​GridPane.setConstraints(object, column ,​row)''​.\\ \\ În interfaţa grafică se folosesc cinci butoane (adăugare, editare, ştergere, căutare, golire conținut) pentru a se realiza operaţiile de tip CRUD.\\ În momentul când se produce o acţiune corespunzătoare unuia dintre aceste acestea, se vor apela metodele corespunzătoare evenimentului de tip ''​onAction()'',​ specificate în fișierul FXML.\\ {{ :​laboratoare:​laborator03:​activitate_de_laborator02.png?​nolink }}\\ +**3**. În clasa ''​TableManagement'',​ din pachetul ''​ro.pub.cs.aipi.lab09.controller''​ să se completeze metoda ''​initialize()'',​ astfel încât aceasta să populeze obiectul ''​attributesGridPane'' ​(de tip ''​GridPane''​) ​care va avea pe două coloane obiectele de tip ''​ArrayList<​Label>''​ (''​attributeLabels''​),​ respectiv ''​ArrayList<​Control>''​ (''​attributeControls''​). 
 + 
 +{{ :​laboratoare:​laborator09:​activitate_de_laborator06.png?​nolink }} 
 + 
 +<note important>​Obictele ''​attributeLabels'',​ respectiv ''​attributesControls''​ au deja conținutul care trebuie vizualizat în cadrul acestora.</​note>​ 
 + 
 +<​spoiler|Indicații de Rezolvare>​ 
 +Înainte de a adăuga obiectul propriu-zis,​ trebuie să îi specificaţi poziţia în cadrul obiectului de tip ''​GridPane'',​ prin intermediul metodei ​[[https://​docs.oracle.com/​javafx/​2/​api/​javafx/​scene/​layout/​GridPane.html#​setConstraints%28javafx.scene.Node,​%20int,​%20int%29|GridPane.setConstraints(Node, column ,row)]]. 
 + 
 +Atașarea propriu-zisă a nodului se face prin intermediul metodei ​''​add()''​ apelată pe lista observabilă a nodurilor (copil) a obiectului ''​attributesGridPane'',​ obținută prin invocarea metodei [[https://​docs.oracle.com/​javafx/​2/​api/​javafx/​scene/​layout/​Pane.html#​getChildren%28%29|getChildren()]]. 
 + 
 +<code java> 
 +GridPane.setConstraints(attributesLabels.get(attributesLabels.size() - 1), 0, currentIndex);​ 
 +attributesGridPane.getChildren().add(attributesLabels.get(attributesLabels.size() - 1)); 
 + 
 +// ... 
 + 
 +GridPane.setConstraints(attributesControls.get(attributesControls.size() - 1), 1, currentIndex);​ 
 +attributesGridPane.getChildren().add(attributesControls.get(attributesControls.size() - 1)); 
 +</​code>​ 
 + 
 +Toate aceste operații vor fi realizate repetitiv, pe o iterație care parcurge toate atributele din cadrul entității respective. 
 + 
 +</​spoiler>​ 
 + 
 +Așa cum se poate observa, în interfaţa grafică se folosesc cinci butoane (adăugare, editare, ştergere, căutare, golire conținut) pentru a se realiza operaţiile de tip CRUD (Create, Read, Update, Delete).\\ În momentul când se produce o acţiune corespunzătoare unuia dintre aceste acestea, se vor apela metodele corespunzătoare evenimentului de tip ''​onAction()'',​ specificate în fișierul FXML.
  
 **4**. În clasa ''​TableManagement'',​ din pachetul ''​ro.pub.cs.aipi.lab09.controller'',​ să se implementeze metoda ''​updateButtonHandler()''​ corespunzătoare butonului care actualizează valorile din controale (câmpuri text și liste de selecție) în tabelă. **4**. În clasa ''​TableManagement'',​ din pachetul ''​ro.pub.cs.aipi.lab09.controller'',​ să se implementeze metoda ''​updateButtonHandler()''​ corespunzătoare butonului care actualizează valorile din controale (câmpuri text și liste de selecție) în tabelă.
 +
 +<​spoiler|Indicații de Rezolvare>​
 +În cadrul metodei ''​updateButttonHandler()''​ trebuie realizate următoarele operații:
 +  - se obține indexul selectat în mod curent în cadrul tabelului (astfel încât selecția să poată fi refăcută ulterior operației de actualizare) <code java>
 +int tableViewSelectedIndex = tableContentTableView.getSelectionModel().getSelectedIndex();​
 +</​code>​
 +  - se obține o listă cu toate valorile selectate în mod curent (astfel încât operația de actualizare să fie realizată pe baza identificatorului care are rol de cheie primară în tabelă) <code java>
 +List<​String>​ tableViewCurrentRecord = ((Model) tableContentTableView.getSelectionModel().getSelectedItem()).getValues();​
 +</​code>​
 +  - se parcurge lista de etichete / controale, astfel încât să se construiască:​
 +    - lista de atribute, pe baza listei de etichete <code java>
 +attributes.add(attributesLabels.get(currentIndex).getText());​
 +</​code>​
 +    - lista de valori: se obține conținutul listei derulante și pe baza ei se determină identificatorul înregistrării din tabela referită, prin intermediul metodei ''​getForeignKeyValue()''​ care primește ca argumente denumirea tabelei, denumirea atributului precum și lista cu valori <code java>
 +if (attributeControl instanceof ComboBox) {
 +  try {
 +    String parentTableValues = ((ComboBox<​String>​) attributeControl).getValue();​
 +    if (parentTableValues != null && !parentTableValues.isEmpty()) {
 +      value = databaseOperations.getForeignKeyValue(tableName,​ attributesLabels.get(currentIndex).getText(),​ Utilities.decompress(parentTableValues));​
 +    }
 +  } catch (Exception sqlException) {
 +    System.out.println("​An exception had occured: " + sqlException.getMessage());​
 +    if (Constants.DEBUG) {
 +      sqlException.printStackTrace();​
 +    }
 +  }
 +} else {
 +  value = ((TextField) attributeControl).getText();​
 +}
 +if (value != null && !value.isEmpty()) {
 +  values.add(value);​
 +}
 +</​code>​
 +  - actualizarea propriu-zisă este realizată prin intermediul metodei ''​updateRecordsIntoTable()''​ care primește ca parametrii denumirea tabelei, lista de atribute, lista de valori precum și condiția pentru înregistrarea care este actualizată (pe baza valorii cheii primare, determinată anterior) <code java>
 +try {
 +  if (attributes != null && values != null && !attributes.isEmpty() && !values.isEmpty()) {
 +    databaseOperations.updateRecordsIntoTable(tableName, ​
 +      attributes, ​
 +      values,
 +      databaseOperations.getTablePrimaryKey(tableName) + "​=\'"​ + tableViewCurrentRecord.get(0) + "​\'"​);​
 +  }
 +} catch (SQLException | DatabaseException exception) {
 +  System.out.println("​An exception had occured: " + exception.getMessage());​
 +  if (Constants.DEBUG) {
 +    exception.printStackTrace();​
 +  }
 +}
 +</​code>​
 +  - popularea tabelei cu noul conținut implică:
 +    - apelarea metodei ''​populate'',​ fără nici un criteriu de selecție;
 +    - selectarea valorii care a fost actualizată:​ ''​tableContentTableView.getSelectionModel().select(tableViewSelectedIndex);'';​
 +  - valorile corespunzătoare selecției curente nu mai sunt vizualizate în cadrul listei de controale; în acest scop se poate invoca metoda de tratare a evenimentului de apăsare a butonului //Clear//, fără nici un argument ca eveniment propriu-zis:​ <code java>
 +clearButtonHandler(null);​
 +</​code>​
 +</​spoiler>​
  
 **5**. În clasa ''​TableManagement'',​ din pachetul ''​ro.pub.cs.aipi.lab09.controller'',​ să se implementeze metoda ''​clearButtonHandler()''​ care curăță conținutul câmpurilor text și al listelor de selecție, lăsând completată numai valoarea corespunzătoare cheii primare autoincrementale cu următoarea valoare din baza de date. **5**. În clasa ''​TableManagement'',​ din pachetul ''​ro.pub.cs.aipi.lab09.controller'',​ să se implementeze metoda ''​clearButtonHandler()''​ care curăță conținutul câmpurilor text și al listelor de selecție, lăsând completată numai valoarea corespunzătoare cheii primare autoincrementale cu următoarea valoare din baza de date.
 +
 +<​spoiler|Indicații de Rezolvare>​
 +Se parcurge, în cadrul unei iterații, lista de controale, acestea putând avea tipul:
 +  - ''​ComboBox'':​ se folosește metoda ''​setValue()''​ primind ca argument șirul vid: ''​%%((ComboBox<​String>​) attributeControl).setValue(""​);​%%'';​
 +  - ''​TextField'':​ se utilizează metoda ''​setText()''​ primind ca argument:
 +    - valoarea maximă a cheii primare în cadrul tabelei (pentru indexul 0, corespunzător identificatorului),​ prin intermediul metodei ''​getTablePrimaryKeyMaximimValue()'',​ disponibilă în interfața ''​DatabaseOperations'':​ ''​%%((TextField) attributeControl).setText(Integer.toString(databaseOperations.getTablePrimaryKeyMaximumValue(tableName) + 1));​%%'';​
 +    - șirul vid, altfel: ''​%%((TextField) attributeControl).setText(""​);​%%''​.
 +</​spoiler>​
  
 **6**. Să se creeze un submeniu ''​About''​ al meniului ''​Help''​ care în momentul când este accesat deschide o fereastră în care sunt afişate pictograma (fișierul ''​icon.png''​ din directorul ''​resources/​images''​) și denumirea aplicaţiei,​ versiunea şi anul în care a fost realizată. Totodată, aceasta va conţine un buton care va închide fereastra atunci când este apăsat.\\ Se poate folosi clasa ''​Dialog''​ în acest sens. **6**. Să se creeze un submeniu ''​About''​ al meniului ''​Help''​ care în momentul când este accesat deschide o fereastră în care sunt afişate pictograma (fișierul ''​icon.png''​ din directorul ''​resources/​images''​) și denumirea aplicaţiei,​ versiunea şi anul în care a fost realizată. Totodată, aceasta va conţine un buton care va închide fereastra atunci când este apăsat.\\ Se poate folosi clasa ''​Dialog''​ în acest sens.
 +
 +<​spoiler|Indicații de Rezolvare>​
 +În clasa ''​Container''​ din pachetul ''​ro.pub.cs.aipi.lab09.controller''​ se instanțiază un obiect de tip ''​Dialog''​ pentru care se specifică următoarele proprietăți:​
 +  * titlul este ''​Constants.ABOUT_WINDOW_TITLE'';​
 +  * locația de la care se va încărca pictograma este ''​Constants.ABOUT_ICON_LOCATION'';​
 +  * mesajul care va fi vizualizat este ''​Constants.ABOUT_MESSAGE_CONTENT''​.
 +Fereastra trebuie afișată prin invocarea metodei ''​start()''​.
 +
 +<code java>
 +Dialog dialog = new Dialog();
 +dialog.setProperties(Constants.ABOUT_WINDOW_TITLE,​ Constants.ABOUT_ICON_LOCATION,​ Constants.ABOUT_MESSAGE_CONTENT);​
 +dialog.start();​
 +</​code>​
 +</​spoiler>​
  
 **7**. Să se creeze un buton de căutare la apăsarea căruia vor fi afişate în tabel toate înregistrările care corespund unor anumite criterii (au anumite valori corespunzătoare unor anumite atribute, specificate de utilizator în câmpurile text şi listele derulante, ignorând cheia primară). **7**. Să se creeze un buton de căutare la apăsarea căruia vor fi afişate în tabel toate înregistrările care corespund unor anumite criterii (au anumite valori corespunzătoare unor anumite atribute, specificate de utilizator în câmpurile text şi listele derulante, ignorând cheia primară).
  
-**8**. Să se creeze o animaţie asupra butonului deasupra căruia se găseşte mouse-ul astfel încât acesta să aibă un efect de tip umbră exterioară (''​DropShadow''​) implementând şi o tranziţie care pe parcursul unei secunde modifică transparenţa de la 1.0 la 0.8 şi scalează dimensiunile cu 0.1. Animaţia trebuie cât timp mouse-ul se găseşte deasupra butonului având un caracter ciclic. Metoda se va implementa pentru toate butoanele ce realizează modificări asupra înregistrărilor din baza de date.+<​spoiler|Indicații de Rezolvare>​ 
 +În clasa ''​TableManagement''​ din pachetul ''​ro.pub.cs.aipi.lab09.controller'',​ se va implementa metoda ''​searchButtonHandler()'',​ în cadrul căreia va fi parcursă, în cadrul unei iterații, lista de controale, pentru a se obține perechea de atribute și de valori pe baza cărora va fi realizată căutarea. 
 +  - dacă controlul este de tip ''​ComboBox''​ se identifică valoarea din tabela referită corespunzătoare atributului,​ prin invocarea metodei ''​getForeignKeyValue()'':​ <code java> 
 +if (attributeControl instanceof ComboBox) { 
 +  try { 
 +    String parentTableValues = ((ComboBox<​String>​) attributeControl).getValue();​ 
 +    if (parentTableValues != null && !parentTableValues.isEmpty()) { 
 +      value = databaseOperations.getForeignKeyValue(tableName,​ attributesLabels.get(currentIndex).getText(),​ Utilities.decompress(parentTableValues));​ 
 +    } 
 +  } catch (Exception exception) { 
 +    System.out.println("​An exception had occured: " + exception.getMessage());​ 
 +    if (Constants.DEBUG) { 
 +      exception.printStackTrace();​ 
 +    } 
 +  } 
 +} 
 +</​code>​  
 +  - în situația în care controlul este de tip ''​TextField'',​ se identifică valoarea prin intermediul metodei ''​getText()'':​ ''​%%value = ((TextField) attributeControl).getText();​%%''​ 
 + 
 +Se construiește clauza ''​WHERE''​ a interogării pe baza căreia este realizată căutarea folosind șablonul ''​atribut='​%valoare%''',​ aceasta fiind transmisă ca parametru al metodei ''​populateTableView()'':​ <code java> 
 +for (Control attributeControl : attributesControls) { 
 +  // ... 
 +  if (value != null && !value.isEmpty() && currentIndex != 0) { 
 +    whereClause += ((whereClause.isEmpty()) ? ""​ : " AND ") + attributesLabels.get(currentIndex).getText() + " LIKE \'​%"​ + Utilities.escape(value) + "​%\'";​ 
 +  } 
 +  currentIndex++;​ 
 +  // ... 
 +} 
 +populateTableView(!whereClause.isEmpty() ? whereClause : null); 
 +</​code>​ 
 +</​spoiler>​ 
 + 
 +**8**. Să se creeze o animaţie asupra butonului deasupra căruia se găseşte mouse-ul astfel încât acesta să aibă un efect de tip umbră exterioară ([[https://​docs.oracle.com/​javafx/​2/​api/​javafx/​scene/​effect/​DropShadow.html|DropShadow]]) implementând şi o tranziţie care pe parcursul unei secunde modifică transparenţa de la 1.0 la 0.8 şi scalează dimensiunile cu 0.1. Animaţia trebuie cât timp mouse-ul se găseşte deasupra butonului având un caracter ciclic. Metoda se va implementa pentru toate butoanele ce realizează modificări asupra înregistrărilor din baza de date. 
 + 
 +<​spoiler|Indicații de Rezolvare>​ 
 +Se creează următoarele efecte: 
 +  - o umbră care va fi aplicată butoanelor (un obiect de tip ''​DropShadow''​);​ 
 +  - o animație de tip dispariție având transparențele variabile între 1 și 0.8, cu durata de 1 secundă, care se va repeta nedefinit (un obiect de tip ''​FadeTransition''​);​ 
 +  - o animație de tip scalare, având valorile de 0.1 atât pe axa Ox cât și pe aza Oy, cu durata de 1 secundă, care va rula nedefinit (un obiect de tip ''​ScaleTransition''​);​ 
 +  - un efect paralel, care include animațiile de tip dispariție,​ respectiv scalare, care vor fi aplicate concomitent (un obiect de tip ''​ParallelTransition''​). 
 + 
 +<code java> 
 +final DropShadow dropShadow = new DropShadow();​ 
 +final FadeTransition fadeTransition = new FadeTransition(Duration.seconds(1));​ 
 +fadeTransition.setFromValue(1.0f);​ 
 +fadeTransition.setToValue(0.8f);​ 
 +fadeTransition.setCycleCount(Timeline.INDEFINITE);​ 
 +fadeTransition.setAutoReverse(true);​ 
 +final ScaleTransition scaleTransition = new ScaleTransition(Duration.seconds(1));​ 
 +scaleTransition.setByX(0.1f);​ 
 +scaleTransition.setByY(0.1f);​ 
 +scaleTransition.setCycleCount(Timeline.INDEFINITE);​ 
 +scaleTransition.setAutoReverse(true);​ 
 +final ParallelTransition parallelTransition = new ParallelTransition(fadeTransition,​ scaleTransition);​ 
 +</​code>​ 
 + 
 +Pentru fiecare buton în parte, se vor defini metodele ascultător pentru fiecare dintre cele două evenimente:​ 
 +  - ''​MouseEvent.MOUSE_ENTERED''​ - se sta stabilește efectul de tip umbră, se transmite nodul ca obiect al animațiilor de tipul ''​Fade''​ și ''​Scale'',​ după care tranziția paralelă este începută , folosind metoda ''​play()'';​ 
 +  - ''​MouseEvent.MOUSE_EXITED''​ - se pierd efectele anterioare (metoda ''​setEfect()''​ primește argumentul null), durata animației devine 0, animațiile pierd referința de pe nod, iar tranziția paralelă este oprită, folosind metoda ''​stop()''​. 
 + 
 +<code java> 
 +buttonList.stream().map((currentButton) -> { 
 +  currentButton.addEventHandler(MouseEvent.MOUSE_ENTERED,​ (MouseEvent event) -> { 
 +    currentButton.setEffect(dropShadow);​ 
 +    fadeTransition.setNode(currentButton);​ 
 +    scaleTransition.setNode(currentButton);​ 
 +    parallelTransition.play();​ 
 +  }); 
 +  return currentButton;​ 
 +}).forEach((currentButton) -> { 
 +  currentButton.addEventHandler(MouseEvent.MOUSE_EXITED,​ (MouseEvent event) -> { 
 +    currentButton.setEffect(null);​ 
 +    parallelTransition.jumpTo(Duration.ZERO);​ 
 +    fadeTransition.setNode(null);​ 
 +    scaleTransition.setNode(null);​ 
 +    parallelTransition.stop();​ 
 +    parallelTransition.setNode(null);​ 
 +  }); 
 +}); 
 +</​code>​ 
 +</​spoiler>​
  
 ===== Resurse ====== ===== Resurse ======
Line 2283: Line 2499:
 ===== Soluții ===== ===== Soluții =====
  
-TODO+[[https://​github.com/​aipi2015/​Laborator09/​tree/​master/​solutions/​eclipse/​09-BookStore-JavaFX|Proiect Eclipse]]\\  
 +[[https://​github.com/​aipi2015/​Laborator09/​tree/​master/​solutions/​netbeans/​09-BookStore-JavaFX|Proiect NetBeans]]
laboratoare/laborator09.1450390291.txt.gz · Last modified: 2015/12/18 00:11 by Andrei Roșu-Cojocaru
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0